From 74e04082017b35e284be40de36be45878baa8430 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 9 Feb 2025 20:06:15 +0100 Subject: [PATCH 001/158] Current WIP CD-ROM changes. --- src/cdrom/cdrom.c | 692 +++++++++++++++++++------------- src/cdrom/cdrom_image.c | 2 +- src/disk/hdc_ide.c | 196 ++++++--- src/disk/hdc_ide_sff8038i.c | 2 +- src/include/86box/cdrom.h | 62 +-- src/include/86box/device.h | 29 +- src/include/86box/hdc_ide.h | 2 + src/include/86box/hdd.h | 86 ++-- src/include/86box/mo.h | 9 +- src/include/86box/scsi_cdrom.h | 16 +- src/include/86box/scsi_device.h | 28 +- src/include/86box/scsi_disk.h | 1 + src/include/86box/zip.h | 1 + src/qt/qt_winrawinputfilter.cpp | 1 + src/qt/win_cdrom_ioctl.c | 14 + src/scsi/scsi_cdrom.c | 646 ++++++++++++++++++----------- src/sound/sound.c | 150 +++---- 17 files changed, 1201 insertions(+), 736 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 2cdcc5a22..9e6c57e70 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -89,8 +89,10 @@ static char * cdrom_modes[4] = { "Mode 1", "Mode 2", "CD-I/ static uint8_t cdrom_mode_masks[14] = { 0x0f, 0x00, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x05, 0x05, 0x04, 0x04, 0x0c, 0x0c }; -static uint8_t status_codes[2][8] = { { 0x13, 0x15, 0x15, 0x15, 0x12, 0x11, 0x13, 0x13 }, - { 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00 } }; +static uint8_t status_codes[2][16] = { { 0x13, 0x15, 0x15, 0x15, 0x12, 0x11, 0x13, 0x13, + 0x12, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15 }, + { 0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static int mult = 1; static int part = 0; static int ecc_diff = 288; @@ -122,7 +124,7 @@ static const struct { static void cdrom_generate_name(const int type, char *name, const int internal) { - char elements[3][2048] = { 0 }; + char elements[3][512] = { 0 }; memcpy(elements[0], cdrom_drive_types[type].vendor, strlen(cdrom_drive_types[type].vendor) + 1); @@ -286,32 +288,39 @@ msf_to_bcd(int *m, int *s, int *f) static int read_data(cdrom_t *dev, const uint32_t lba) { - return dev->ops->read_sector(dev->local, dev->raw_buffer, lba); + int ret = 1; + + if (dev->cached_sector != lba) { + dev->cached_sector = lba; + + ret = dev->ops->read_sector(dev->local, + dev->raw_buffer[dev->cur_buf ^ 1], lba); + + if (ret <= 0) { + memset(dev->raw_buffer[dev->cur_buf ^ 1], 0x00, 2448); + dev->cached_sector = -1; + } + + dev->cur_buf ^= 1; + } + + return ret; } static void cdrom_get_subchannel(cdrom_t *dev, const uint32_t lba, subchannel_t *subc, const int cooked) { - const uint8_t *scb; - uint32_t scb_offs = 0; uint8_t q[16] = { 0 }; + if (lba != dev->cached_sector) + dev->cached_sector = -1; - if ((lba == dev->seek_pos) && - ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED))) - scb = dev->subch_buffer; - else { - scb = (const uint8_t *) dev->raw_buffer; - scb_offs = 2352; - - memset(dev->raw_buffer, 0, 2448); - - (void) read_data(dev, lba); - } + (void) read_data(dev, lba); for (int i = 0; i < 12; i++) for (int j = 0; j < 8; j++) - q[i] |= ((scb[scb_offs + (i << 3) + j] >> 6) & 0x01) << (7 - j); + q[i] |= ((dev->raw_buffer[dev->cur_buf][RAW_SECTOR_SIZE + + (i << 3) + j] >> 6) & 0x01) << (7 - j); if (cooked) { uint8_t temp = (q[0] >> 4) | ((q[0] & 0xf) << 4); @@ -406,7 +415,7 @@ find_specific_track(const raw_track_info_t *trti, const int num, const int track static int read_toc_normal(const cdrom_t *dev, unsigned char *b, - const unsigned char start_track, const int msf, + unsigned char start_track, const int msf, const int sony) { uint8_t rti[65536] = { 0 }; @@ -417,8 +426,13 @@ read_toc_normal(const cdrom_t *dev, unsigned char *b, int len = 4; int t = -1; - cdrom_log(dev->log, "read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i)\n", + if ((dev->is_bcd || dev->is_chinon) && (start_track < 0xa0)) + start_track = bcd2bin(start_track); + + cdrom_log(dev->log, "read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i, %i)\n", (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); + pclog("read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i, %i)\n", + (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); dev->ops->get_raw_track_info(dev->local, &num, rti); @@ -458,7 +472,11 @@ read_toc_normal(const cdrom_t *dev, unsigned char *b, if (!sony) b[len++] = 0; /* Reserved */ b[len++] = tprti[i].adr_ctl; /* ADR/CTL */ - b[len++] = tprti[i].point; /* Track number */ + if ((dev->is_bcd || dev->is_chinon) && (tprti[i].point >= 1) && + (tprti[i].point <= 99)) + b[len++] = bin2bcd(tprti[i].point); /* Track number */ + else + b[len++] = tprti[i].point; /* Track number */ if (!sony) b[len++] = 0; /* Reserved */ @@ -466,7 +484,7 @@ read_toc_normal(const cdrom_t *dev, unsigned char *b, b[len++] = 0; /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) { + if (dev->is_bcd) { int m = tprti[i].pm; int s = tprti[i].ps; int f = tprti[i].pf; @@ -527,14 +545,18 @@ read_toc_session(const cdrom_t *dev, unsigned char *b, const int msf) if (first != NULL) { b[len++] = 0x00; b[len++] = first->adr_ctl; - b[len++] = first->point; + if ((dev->is_bcd || dev->is_chinon) && (first->point >= 1) && + (first->point <= 99)) + b[len++] = bin2bcd(first->point); + else + b[len++] = first->point; b[len++] = 0x00; if (msf) { b[len++] = 0x00; /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) { + if (dev->is_bcd) { int m = first->pm; int s = first->ps; int f = first->pf; @@ -586,6 +608,16 @@ read_toc_raw(const cdrom_t *dev, unsigned char *b, const unsigned char start_tra if (num != 0) for (int i = 0; i < num; i++) if (t[i].session >= start_track) { memcpy(&(b[len]), &(t[i]), 11); + + if ((dev->is_bcd || dev->is_chinon) && (b[3] >= 1) && (b[3] <= 99)) + b[3] = bin2bcd(b[3]); + + for (int j = 0; j < 3; j++) + if (dev->is_bcd) { + b[4 + j] = bin2bcd(b[4 + j]); + b[8 + j] = bin2bcd(b[8 + j]); + } + len += 11; } @@ -642,9 +674,9 @@ track_type_is_valid(UNUSED(const cdrom_t *dev), const int type, const int flags, static int read_audio(cdrom_t *dev, const uint32_t lba, uint8_t *b) { - const int ret = dev->ops->read_sector(dev->local, dev->raw_buffer, lba); + const int ret = read_data(dev, lba); - memcpy(b, dev->raw_buffer, 2352); + memcpy(b, dev->raw_buffer[dev->cur_buf], 2352); dev->cdrom_sector_size = 2352; @@ -660,7 +692,7 @@ process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[Mode 1] Sync\n"); - memcpy(b, dev->raw_buffer, 12); + memcpy(b, dev->raw_buffer[dev->cur_buf], 12); dev->cdrom_sector_size += 12; b += 12; } @@ -668,7 +700,7 @@ process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[Mode 1] Header\n"); - memcpy(b, dev->raw_buffer + 12, 4); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 12, 4); dev->cdrom_sector_size += 4; b += 4; } @@ -678,7 +710,7 @@ process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) if (!(cdrom_sector_flags & 0x10)) { /* No user data */ cdrom_log(dev->log, "[Mode 1] Sub-header\n"); - memcpy(b, dev->raw_buffer + 16, 8); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16, 8); dev->cdrom_sector_size += 8; b += 8; } @@ -688,12 +720,12 @@ process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) /* User data */ cdrom_log(dev->log, "[Mode 1] User data\n"); if (mult > 1) { - memcpy(b, dev->raw_buffer + 16 + (part * dev->sector_size), - dev->sector_size); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16 + + (part * dev->sector_size), dev->sector_size); dev->cdrom_sector_size += dev->sector_size; b += dev->sector_size; } else { - memcpy(b, dev->raw_buffer + 16, 2048); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16, 2048); dev->cdrom_sector_size += 2048; b += 2048; } @@ -702,7 +734,7 @@ process_mode1(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ cdrom_log(dev->log, "[Mode 1] EDC/ECC\n"); - memcpy(b, dev->raw_buffer + 2064, (288 - ecc_diff)); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 2064, (288 - ecc_diff)); dev->cdrom_sector_size += (288 - ecc_diff); } } @@ -716,7 +748,7 @@ process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[Mode 2 Formless] Sync\n"); - memcpy(b, dev->raw_buffer, 12); + memcpy(b, dev->raw_buffer[dev->cur_buf], 12); dev->cdrom_sector_size += 12; b += 12; } @@ -724,7 +756,7 @@ process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[Mode 2 Formless] Header\n"); - memcpy(b, dev->raw_buffer + 12, 4); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 12, 4); dev->cdrom_sector_size += 4; b += 4; } @@ -733,7 +765,7 @@ process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[Mode 2 Formless] Sub-header\n"); - memcpy(b, dev->raw_buffer + 16, 8); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16, 8); dev->cdrom_sector_size += 8; b += 8; } @@ -741,7 +773,7 @@ process_mode2_non_xa(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x10) { /* User data */ cdrom_log(dev->log, "[Mode 2 Formless] User data\n"); - memcpy(b, dev->raw_buffer + 24, (2336 - ecc_diff)); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 24, (2336 - ecc_diff)); dev->cdrom_sector_size += (2336 - ecc_diff); } } @@ -755,7 +787,7 @@ process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Sync\n"); - memcpy(b, dev->raw_buffer, 12); + memcpy(b, dev->raw_buffer[dev->cur_buf], 12); dev->cdrom_sector_size += 12; b += 12; } @@ -763,7 +795,7 @@ process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Header\n"); - memcpy(b, dev->raw_buffer + 12, 4); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 12, 4); dev->cdrom_sector_size += 4; b += 4; } @@ -771,7 +803,7 @@ process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[XA Mode 2 Form 1] Sub-header\n"); - memcpy(b, dev->raw_buffer + 16, 8); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16, 8); dev->cdrom_sector_size += 8; b += 8; } @@ -780,12 +812,12 @@ process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, /* User data */ cdrom_log(dev->log, "[XA Mode 2 Form 1] User data\n"); if (mult > 1) { - memcpy(b, dev->raw_buffer + 24 + (part * dev->sector_size), - dev->sector_size); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 24 + + (part * dev->sector_size), dev->sector_size); dev->cdrom_sector_size += dev->sector_size; b += dev->sector_size; } else { - memcpy(b, dev->raw_buffer + 24, 2048); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 24, 2048); dev->cdrom_sector_size += 2048; b += 2048; } @@ -794,7 +826,7 @@ process_mode2_xa_form1(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ cdrom_log(dev->log, "[XA Mode 2 Form 1] EDC/ECC\n"); - memcpy(b, dev->raw_buffer + 2072, (280 - ecc_diff)); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 2072, (280 - ecc_diff)); dev->cdrom_sector_size += (280 - ecc_diff); } } @@ -808,7 +840,7 @@ process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x80) { /* Sync */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Sync\n"); - memcpy(b, dev->raw_buffer, 12); + memcpy(b, dev->raw_buffer[dev->cur_buf], 12); dev->cdrom_sector_size += 12; b += 12; } @@ -816,7 +848,7 @@ process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x20) { /* Header */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Header\n"); - memcpy(b, dev->raw_buffer + 12, 4); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 12, 4); dev->cdrom_sector_size += 4; b += 4; } @@ -824,7 +856,7 @@ process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x40) { /* Sub-header */ cdrom_log(dev->log, "[XA Mode 2 Form 2] Sub-header\n"); - memcpy(b, dev->raw_buffer + 16, 8); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 16, 8); dev->cdrom_sector_size += 8; b += 8; } @@ -832,14 +864,14 @@ process_mode2_xa_form2(cdrom_t *dev, const int cdrom_sector_flags, if (cdrom_sector_flags & 0x10) { /* User data */ cdrom_log(dev->log, "[XA Mode 2 Form 2] User data\n"); - memcpy(b, dev->raw_buffer + 24, (2328 - ecc_diff)); + memcpy(b, dev->raw_buffer[dev->cur_buf] + 24, + (2328 - ecc_diff)); dev->cdrom_sector_size += (2328 - ecc_diff); } } static void -process_ecc_and_subch(cdrom_t *dev, const int cdrom_sector_flags, - uint8_t *b) +process_c2(cdrom_t *dev, const int cdrom_sector_flags, uint8_t *b) { if ((cdrom_sector_flags & 0x06) == 0x02) { /* Add error flags. */ @@ -851,31 +883,65 @@ process_ecc_and_subch(cdrom_t *dev, const int cdrom_sector_flags, cdrom_log(dev->log, "Full error flags\n"); memcpy(b + dev->cdrom_sector_size, dev->extra_buffer, 296); dev->cdrom_sector_size += 296; - } + } +} + +static void +cdrom_deinterleave_subch(uint8_t *d, const uint8_t *s) +{ + for (int i = 0; i < 8 * 12; i++) { + int dmask = 0x80; + int smask = 1 << (7 - (i / 12)); + + (*d) = 0; + + for (int j = 0; j < 8; j++) { + (*d) |= (s[(i % 12) * 8 + j] & smask) ? dmask : 0; + dmask >>= 1; + } + + d++; + } +} + +static void +process_c2_and_subch(cdrom_t *dev, const int cdrom_sector_flags, + uint8_t *b) +{ + if (dev->c2_first) + process_c2(dev, cdrom_sector_flags, b); if ((cdrom_sector_flags & 0x700) == 0x100) { cdrom_log(dev->log, "Raw subchannel data\n"); - memcpy(b + dev->cdrom_sector_size, dev->raw_buffer + 2352, 96); + memcpy(b + dev->cdrom_sector_size, dev->raw_buffer[dev->cur_buf] + + 2352, 96); dev->cdrom_sector_size += 96; } else if ((cdrom_sector_flags & 0x700) == 0x200) { cdrom_log(dev->log, "Q subchannel data\n"); - memcpy(b + dev->cdrom_sector_size, dev->raw_buffer + 2352, 16); + memcpy(b + dev->cdrom_sector_size, dev->raw_buffer[dev->cur_buf] + + 2352, 16); dev->cdrom_sector_size += 16; } else if ((cdrom_sector_flags & 0x700) == 0x400) { cdrom_log(dev->log, "R/W subchannel data\n"); - memcpy(b + dev->cdrom_sector_size, dev->raw_buffer + 2352, 96); + cdrom_deinterleave_subch(b + dev->cdrom_sector_size, + dev->raw_buffer[dev->cur_buf] + 2352); dev->cdrom_sector_size += 96; } + + if (!dev->c2_first) + process_c2(dev, cdrom_sector_flags, b); } static void cdrom_drive_reset(cdrom_t *dev) { - dev->priv = NULL; - dev->insert = NULL; - dev->close = NULL; - dev->get_volume = NULL; - dev->get_channel = NULL; + dev->priv = NULL; + dev->insert = NULL; + dev->close = NULL; + dev->get_volume = NULL; + dev->get_channel = NULL; + + dev->cached_sector = -1; if (cdrom_drive_types[dev->type].speed == -1) dev->real_speed = dev->speed; @@ -890,7 +956,8 @@ cdrom_unload(cdrom_t *dev) cdrom_log(dev->log, "CDROM: cdrom_unload(%s)\n", dev->image_path); } - dev->cd_status = CD_STATUS_EMPTY; + dev->cd_status = CD_STATUS_EMPTY; + dev->cached_sector = -1; if (dev->local != NULL) { dev->ops->close(dev->local); @@ -900,6 +967,39 @@ cdrom_unload(cdrom_t *dev) dev->ops = NULL; } +#ifdef ENABLE_CDROM_LOG +static void +cdrom_toc_dump(cdrom_t *dev) +{ + uint8_t b[65536] = { 0 }; + int len = cdrom_read_toc(dev, b, CD_TOC_RAW, 0, 0, 65536); + const char *fn2 = "d:\\86boxnew\\toc_cue.dmp"; + FILE * f = fopen(fn2, "wb"); + fwrite(b, 1, len, f); + fflush(f); + fclose(f); + cdrom_log(dev->log, "Written TOC of %i bytes to %s\n", len, fn2); + + memset(b, 0x00, 65536); + len = cdrom_read_toc(dev, b, CD_TOC_NORMAL, 0, 0, 65536); + fn2 = "d:\\86boxnew\\toc_cue_cooked.dmp"; + f = fopen(fn2, "wb"); + fwrite(b, 1, len, f); + fflush(f); + fclose(f); + cdrom_log(dev->log, "Written cooked TOC of %i bytes to %s\n", len, fn2); + + memset(b, 0x00, 65536); + len = cdrom_read_toc(dev, b, CD_TOC_SESSION, 0, 0, 65536); + fn2 = "d:\\86boxnew\\toc_cue_session.dmp"; + f = fopen(fn2, "wb"); + fwrite(b, 1, len, f); + fflush(f); + fclose(f); + cdrom_log(dev->log, "Written session TOC of %i bytes to %s\n", len, fn2); +} +#endif + /* Reset the CD-ROM Interface, whichever one that is. */ void cdrom_interface_reset(void) @@ -1001,24 +1101,6 @@ cdrom_is_generic(const int type) return (cdrom_drive_types[type].speed == -1); } -int -cdrom_has_date(const int type) -{ - /* This will do for now. */ - return !strcmp(cdrom_drive_types[type].vendor, "PIONEER"); -} - -int -cdrom_is_sony(const int type) -{ - /* This will do for now. */ - return (cdrom_drive_types[type].bus_type == BUS_TYPE_SCSI) && - (!strcmp(cdrom_drive_types[type].vendor, "DEC") || - !strcmp(cdrom_drive_types[type].vendor, "ShinaKen") || - !strcmp(cdrom_drive_types[type].vendor, "SONY") || - !strcmp(cdrom_drive_types[type].vendor, "TEXEL")); -} - int cdrom_is_caddy(const int type) { @@ -1067,7 +1149,7 @@ cdrom_get_type_count(void) void cdrom_get_identify_model(const int type, char *name, const int id) { - char elements[2][2048] = { 0 }; + char elements[2][512] = { 0 }; memcpy(elements[0], cdrom_drive_types[type].vendor, strlen(cdrom_drive_types[type].vendor) + 1); @@ -1197,6 +1279,24 @@ cdrom_lba_to_msf_accurate(const int lba) return ((m << 16) | (s << 8) | f); } +void +cdrom_interleave_subch(uint8_t *d, const uint8_t *s) +{ + memset(d, 0x00, 96); + + for (int i = 0; i < 8 * 12; i++) { + int smask = 0x80; + int dmask = 1 << (7 - (i / 12)); + + for (int j = 0; j < 8; j++) { + d[(i % 12) * 8 + j] |= ((*s) & smask) ? dmask : 0; + smask >>= 1; + } + + s++; + } +} + double cdrom_seek_time(const cdrom_t *dev) { @@ -1261,40 +1361,58 @@ cdrom_is_pre(const cdrom_t *dev, const uint32_t lba) return 0; } +#include <86box/filters.h> + +static void +cdrom_audio_deemphasize(int16_t *buffer) +{ + for (int i = 0; i < 588; i++) + for (int j = 0; j < 2; j++) + buffer[(i * 2) + j] = deemph_iir(j, buffer[(i * 2) + j]); +} + int cdrom_audio_callback(cdrom_t *dev, int16_t *output, const int len) { int ret = 1; - if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) { - // cdrom_log(dev->log, "Audio callback while not playing\n"); - if (dev->cd_status == CD_STATUS_PLAYING) - dev->seek_pos += (len >> 11); - memset(output, 0, len * 2); - return 0; - } - while (dev->cd_buflen < len) { if (dev->seek_pos < dev->cd_end) { - if (dev->ops->read_sector(dev->local, - (uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), dev->seek_pos)) { + ret = dev->ops->read_sector(dev->local, + dev->raw_buffer[dev->cur_buf ^ 1], + dev->seek_pos); + if (!dev->sound_on) + memset(dev->raw_buffer[dev->cur_buf ^ 1], 0x00, 2352); + dev->cur_buf ^= 1; + if (ret) { cdrom_log(dev->log, "Read LBA %08X successful\n", dev->seek_pos); - memcpy(dev->subch_buffer, - ((uint8_t *) &(dev->cd_buffer[dev->cd_buflen])) + 2352, 96); + dev->cached_sector = dev->seek_pos; + /* Q subchannel data in bit 6: 4-5-6-7-0-1-2-3. */ + if ((dev->raw_buffer[dev->cur_buf][2353] >> 6) & 0x01) + /* Data sector, copy silence into buffer. */ + memset((uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), + 0x00, RAW_SECTOR_SIZE); + else { + memcpy((uint8_t *) &(dev->cd_buffer[dev->cd_buflen]), + dev->raw_buffer[dev->cur_buf], RAW_SECTOR_SIZE); + if ((dev->raw_buffer[dev->cur_buf][2355] >> 6) & 0x01) + /* De-emphasize pre-emphasized audio. */ + cdrom_audio_deemphasize(&(dev->cd_buffer[dev->cd_buflen])); + } dev->seek_pos++; dev->cd_buflen += (RAW_SECTOR_SIZE / 2); ret = 1; } else { cdrom_log(dev->log, "Read LBA %08X failed\n", dev->seek_pos); memset(&(dev->cd_buffer[dev->cd_buflen]), 0x00, - (BUF_SIZE - dev->cd_buflen) * 2); + (CD_BUF_SIZE - dev->cd_buflen) * 2); dev->cd_status = CD_STATUS_STOPPED; dev->cd_buflen = len; ret = 0; } } else { cdrom_log(dev->log, "Playing completed\n"); - memset(&dev->cd_buffer[dev->cd_buflen], 0x00, (BUF_SIZE - dev->cd_buflen) * 2); + memset(&dev->cd_buffer[dev->cd_buflen], 0x00, (CD_BUF_SIZE - dev->cd_buflen) * 2); dev->cd_status = CD_STATUS_PLAYING_COMPLETED; dev->cd_buflen = len; ret = 0; @@ -1302,9 +1420,12 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, const int len) } memcpy(output, dev->cd_buffer, len * 2); - memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); + memmove(dev->cd_buffer, &dev->cd_buffer[len], (CD_BUF_SIZE - len) * 2); dev->cd_buflen -= len; + if (!dev->sound_on) + ret = 0; + cdrom_log(dev->log, "Audio callback returning %i\n", ret); return ret; } @@ -1313,15 +1434,18 @@ uint8_t cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int ismsf) { track_info_t ti; - uint32_t pos2 = pos; - uint32_t len2 = len; - int ret = 0; + uint32_t pos2 = pos; + uint32_t len2 = len; + int ret = 0; if (dev->cd_status & CD_STATUS_HAS_AUDIO) { cdrom_log(dev->log, "Play audio - %08X %08X %i\n", pos2, len, ismsf); if (ismsf & 0x100) { /* Track-relative audio play. */ + pos2 = ismsf & 0xff; + if ((dev->is_bcd || dev->is_chinon) && (pos2 < 0xa0)) + pos2 = bcd2bin(pos2); ret = dev->ops->get_track_info(dev->local, ismsf & 0xff, 0, &ti); if (ret) pos2 += MSFtoLBA(ti.m, ti.s, ti.f) - 150; @@ -1331,13 +1455,17 @@ cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int cdrom_stop(dev); } } else if ((ismsf == 2) || (ismsf == 3)) { + if ((dev->is_bcd || dev->is_chinon) && (pos2 < 0xa0)) + pos2 = bcd2bin(pos2); ret = dev->ops->get_track_info(dev->local, pos2, 0, &ti); if (ret) { pos2 = MSFtoLBA(ti.m, ti.s, ti.f) - 150; if (ismsf == 2) { /* We have to end at the *end* of the specified track, not at the beginning. */ - ret = dev->ops->get_track_info(dev->local, len, 1, &ti); + if ((dev->is_bcd || dev->is_chinon) && (len2 < 0xa0)) + len2 = bcd2bin(len2); + ret = dev->ops->get_track_info(dev->local, len2, 1, &ti); if (ret) len2 = MSFtoLBA(ti.m, ti.s, ti.f) - 150; else { @@ -1357,7 +1485,7 @@ cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int int f = pos & 0xff; /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) + if (dev->is_bcd) msf_from_bcd(&m, &s, &f); if (pos == 0xffffff) { @@ -1371,7 +1499,7 @@ cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int f = len & 0xff; /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) + if (dev->is_bcd) msf_from_bcd(&m, &s, &f); len2 = MSFtoLBA(m, s, f) - 150; @@ -1391,8 +1519,6 @@ cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int } if (ret) { - dev->audio_muted_soft = 0; - /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. @@ -1400,10 +1526,11 @@ cdrom_audio_play(cdrom_t *dev, const uint32_t pos, const uint32_t len, const int ret = (dev->ops->get_track_type(dev->local, pos2) == CD_TRACK_AUDIO); if (ret) { - dev->seek_pos = pos2; - dev->cd_end = len2; - dev->cd_status = CD_STATUS_PLAYING; - dev->cd_buflen = 0; + dev->seek_diff = ABS(dev->seek_pos - pos2); + dev->seek_pos = pos2; + dev->cd_end = len2; + dev->cd_status = CD_STATUS_PLAYING; + dev->cd_buflen = 0; } else { cdrom_log(dev->log, "LBA %08X not on an audio track\n", pos); cdrom_stop(dev); @@ -1424,6 +1551,8 @@ cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, cdrom_log(dev->log, "Audio Track Search: MSF = %06x, type = %02x, " "playbit = %02x\n", pos, type, playbit); + ret = 1; + switch (type) { case 0x00: if (pos == 0xffffffff) { @@ -1445,39 +1574,37 @@ cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, dev->seek_pos = pos2; break; } case 0x80: - if (pos == 0xffffffff) { - cdrom_log(dev->log, "(Type 2) Search from current position\n"); - pos2 = dev->seek_pos; + track_info_t ti; + + pos2 = (pos2 >> 24) & 0xff; + if (pos2 < 0xa0) + pos2 = bcd2bin(pos2); + ret = dev->ops->get_track_info(dev->local, pos2, 1, &ti); + if (ret) + dev->seek_pos = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + else { + cdrom_log(dev->log, "Unable to get the starting position for " + "track %08X\n", ismsf & 0xff); + cdrom_stop(dev); } - dev->seek_pos = (pos2 >> 24) & 0xff; break; default: break; } - if (pos2 != 0x00000000) - pos2--; + if (ret) { + if (pos2 != 0x00000000) + pos2--; - /* - Do this at this point, since it's at this point that we know the - actual LBA position to start playing from. - */ - if (dev->ops->get_track_type(dev->local, pos2) & CD_TRACK_AUDIO) - dev->audio_muted_soft = 0; - else { - cdrom_log(dev->log, "Track Search: LBA %08X not on an audio track\n", pos); - dev->audio_muted_soft = 1; - if (dev->ops->get_track_type(dev->local, pos) & CD_TRACK_AUDIO) - dev->audio_muted_soft = 0; + cdrom_log(dev->log, "Track Search Toshiba: LBA=%08X.\n", pos); + + dev->cd_end = dev->cdrom_capacity; + dev->cd_buflen = 0; + + dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_HOLD; + + ret = 1; } - - cdrom_log(dev->log, "Track Search Toshiba: Muted?=%d, LBA=%08X.\n", - dev->audio_muted_soft, pos); - dev->cd_buflen = 0; - - dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; - - ret = 1; } return ret; @@ -1501,15 +1628,15 @@ cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t dev->seek_pos = pos2; - dev->audio_muted_soft = 0; - /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (dev->ops->get_track_type(dev->local, pos2) & CD_TRACK_AUDIO) { + dev->cd_end = dev->cdrom_capacity; dev->cd_buflen = 0; - dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED; + + dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_HOLD; ret = 1; } else { @@ -1533,7 +1660,6 @@ cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos) uint32_t pos2 = MSFtoLBA(m, s, f) - 150; dev->cd_end = pos2; - dev->audio_muted_soft = 0; dev->cd_buflen = 0; dev->cd_status = CD_STATUS_PLAYING; @@ -1552,6 +1678,8 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) if (dev->cd_status & CD_STATUS_HAS_AUDIO) { /* Preliminary support, revert if too incomplete. */ + ret = 1; + switch (type) { case 0x00: dev->cd_end = pos2; @@ -1564,7 +1692,19 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) dev->cd_end = pos2; break; } case 0x80: - dev->cd_end = (pos2 >> 24) & 0xff; + track_info_t ti; + + pos2 = (pos2 >> 24) & 0xff; + if (pos2 < 0xa0) + pos2 = bcd2bin(pos2); + ret = dev->ops->get_track_info(dev->local, pos2, 1, &ti); + if (ret) + dev->cd_end = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + else { + cdrom_log(dev->log, "Unable to get the starting position for " + "track %08X\n", ismsf & 0xff); + cdrom_stop(dev); + } break; case 0xc0: if (pos == 0xffffffff) { @@ -1577,55 +1717,32 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) break; } - cdrom_log(dev->log, "Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", - dev->audio_muted_soft, pos2); - dev->cd_buflen = 0; + if (ret) { + cdrom_log(dev->log, "Toshiba Play Audio: LBA=%08X.\n", pos2); - dev->cd_status = CD_STATUS_PLAYING; - - ret = 1; + dev->cd_status = CD_STATUS_PLAYING; + dev->cd_buflen = 0; + } } return ret; } uint8_t -cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type) +cdrom_audio_scan(cdrom_t *dev, const uint32_t pos) { - uint32_t pos2 = pos; - uint8_t ret = 0; + uint32_t pos2 = pos; + uint8_t ret = 0; if (dev->cd_status & CD_STATUS_HAS_AUDIO) { cdrom_log(dev->log, "Audio Scan: MSF = %06x, type = %02x\n", pos, type); - switch (type) { - case 0x00: - if (pos == 0xffffffff) { - cdrom_log(dev->log, "(Type 0) Search from current position\n"); - pos2 = dev->seek_pos; - } - dev->seek_pos = pos2; - break; - case 0x40: { - const int m = bcd2bin((pos >> 24) & 0xff); - const int s = bcd2bin((pos >> 16) & 0xff); - const int f = bcd2bin((pos >> 8) & 0xff); - if (pos == 0xffffffff) { - cdrom_log(dev->log, "(Type 1) Search from current position\n"); - pos2 = dev->seek_pos; - } else - pos2 = MSFtoLBA(m, s, f) - 150; - - dev->seek_pos = pos2; - break; - } case 0x80: - dev->seek_pos = (pos >> 24) & 0xff; - break; - default: - break; + if (pos == 0xffffffff) { + cdrom_log(dev->log, "(Type 0) Search from current position\n"); + pos2 = dev->seek_pos; } + dev->seek_pos = pos2; - dev->audio_muted_soft = 0; /* Do this at this point, since it's at this point that we know the actual LBA position to start playing from. */ if (dev->ops->get_track_type(dev->local, pos) & CD_TRACK_AUDIO) { @@ -1650,8 +1767,8 @@ cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume) uint8_t cdrom_get_current_status(const cdrom_t *dev) { - const uint8_t is_chinon = !strcmp(cdrom_drive_types[dev->type].vendor, "CHINON"); - const uint8_t ret = status_codes[is_chinon][dev->cd_status & CD_STATUS_MASK]; + const uint8_t ret = status_codes[dev->is_chinon] + [dev->cd_status & CD_STATUS_MASK]; return ret; } @@ -1659,9 +1776,14 @@ cdrom_get_current_status(const cdrom_t *dev) void cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) { - subchannel_t subc; + subchannel_t subc; + int base = 0; + int diff = 4; - cdrom_get_subchannel(dev, dev->seek_pos, &subc, 1); + if (dev->cached_sector == -1) + cdrom_get_subchannel(dev, dev->seek_pos, &subc, 1); + else + cdrom_get_subchannel(dev, dev->cached_sector, &subc, 1); cdrom_log(dev->log, "Returned subchannel absolute at %02i:%02i.%02i, " "relative at %02i:%02i.%02i, seek pos = %08x, cd_end = %08x.\n", @@ -1674,17 +1796,29 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position), the rest are stuff like ISRC etc., which can be all zeroes. */ + case 0x00: + if (dev->bus_type == CDROM_BUS_ATAPI) { + // pclog("Format 0 on ATAPI\n"); + break; + } + // pclog("Format 0 on SCSI\n"); + diff = 0; + fallthrough; case 0x01: /* Current position. */ b[1] = subc.attr; - b[2] = subc.track; + if ((dev->is_bcd || dev->is_chinon) && + (subc.track >= 1) && (subc.track <= 99)) + b[2] = bin2bcd(subc.track); + else + b[2] = subc.track; b[3] = subc.index; if (msf) { b[4] = b[8] = 0x00; /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) { + if (dev->is_bcd) { b[5] = bin2bcd(subc.abs_m); b[6] = bin2bcd(subc.abs_s); b[7] = bin2bcd(subc.abs_f); @@ -1714,26 +1848,37 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) b[10] = (dat >> 8) & 0xff; b[11] = dat & 0xff; } - break; + pclog("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + b[ 0], b[ 1], b[ 2], b[ 3], b[ 4], b[ 5], b[ 6], b[ 7], + b[ 8], b[ 9], b[10], b[11]); + if (b[0] != 0x00) + break; + base += 12; + fallthrough; case 0x02: /* UPC - TODO: Finding and reporting the actual UPC data. */ - memset(&(b[1]), 0x00, 19); - memset(&(b[5]), 0x30, 13); + memset(&(b[base]), 0x00, 20 - diff); + base += diff; + memset(&(b[base + 1]), 0x30, 13); /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) - b[19] = bin2bcd(subc.abs_f); + if (dev->is_bcd) + b[base + 15] = bin2bcd(subc.abs_f); else - b[19] = subc.abs_f; - break; + b[base + 15] = subc.abs_f; + if (b[0] != 0x00) + break; + base += 16; + fallthrough; case 0x03: /* ISRC - TODO: Finding and reporting the actual ISRC data. */ - memset(&(b[1]), 0x00, 19); - memset(&(b[5]), 0x30, 12); + memset(&(b[base]), 0x00, 20 - diff); + base += diff; + memset(&(b[base]), 0x30, 12); /* NEC CDR-260 speaks BCD. */ - if (dev->is_early) - b[18] = bin2bcd(subc.abs_f); + if (dev->is_bcd) + b[base + 14] = bin2bcd(subc.abs_f); else - b[18] = subc.abs_f; + b[base + 14] = subc.abs_f; break; default: cdrom_log(dev->log, "b[0] = %02X\n", b[0]); @@ -1842,7 +1987,7 @@ cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b) cdrom_get_subchannel(dev, dev->seek_pos, &subc, 0); - b[0] = subc.attr; + b[0] = (subc.attr >> 4) | ((subc.attr & 0xf) << 4); b[1] = subc.track; b[2] = subc.index; b[3] = subc.rel_m; @@ -1851,6 +1996,10 @@ cdrom_get_current_subcodeq(cdrom_t *dev, uint8_t *b) b[6] = subc.abs_m; b[7] = subc.abs_s; b[8] = subc.abs_f; + + cdrom_log(dev->log, "SubCodeQ: %02X %02X %02X %02X %02X %02X %02X %02X " + "%02X\n", + b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]); } uint8_t @@ -1860,20 +2009,25 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b) cdrom_get_current_subcodeq(dev, b); - if ((dev->cd_status == CD_STATUS_DATA_ONLY) || - (dev->cd_status == CD_STATUS_DVD) || - (dev->cd_status == CD_STATUS_PLAYING_COMPLETED) || - (dev->cd_status == CD_STATUS_STOPPED)) - ret = 0x03; - else - ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op; + switch (dev->cd_status) { + default: case CD_STATUS_EMPTY: + case CD_STATUS_DATA_ONLY: case CD_STATUS_DVD: + case CD_STATUS_STOPPED: case CD_STATUS_PLAYING_COMPLETED: + ret = 0x03; + break; + case CD_STATUS_HOLD: + ret = 0x02; + break; + case CD_STATUS_PAUSED: + ret = 0x01; + break; + case CD_STATUS_PLAYING: + ret = 0x00; + break; + } - /*If a valid audio track is detected with audio on, unmute it.*/ - if (dev->ops->get_track_type(dev->local, dev->seek_pos) & CD_TRACK_AUDIO) - dev->audio_muted_soft = 0; - - cdrom_log(dev->log, "SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", - dev->seek_pos, dev->cd_end, dev->audio_muted_soft); + cdrom_log(dev->log, "SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x.\n", + dev->seek_pos, dev->cd_end); return ret; } @@ -2041,14 +2195,11 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, switch (type) { case 0: if (num > 0) { - first = find_track(trti, num, 1); - const int last = find_track(trti, num, 0); - - if ((first == -1) || (last == -1)) + if (num < 4) ret = 0; else { - b[0] = bin2bcd(first); - b[1] = bin2bcd(last); + b[0] = bin2bcd(trti[0].pm); + b[1] = bin2bcd(trti[1].pm); b[2] = 0x00; b[3] = 0x00; @@ -2108,7 +2259,7 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b, b[0x12] = temp; } } else { - b[0] = 0x00; /* Audio or CDROM disc. */ + b[0] = trti[0].ps; /* Disc type. */ if (num > 0) first = find_track(trti, num, 1); @@ -2195,7 +2346,6 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int if (dm != CD_TRACK_NORMAL) mode2 = 1; - memset(dev->raw_buffer, 0, 2448); memset(dev->extra_buffer, 0, 296); if ((cdrom_sector_flags & 0xf8) == 0x08) { @@ -2228,28 +2378,29 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int if (ret > 0) { int form = 0; - if ((dev->raw_buffer[0x000f] == 0x00) || - (dev->raw_buffer[0x000f] > 0x02)) { + if ((dev->raw_buffer[dev->cur_buf][0x000f] == 0x00) || + (dev->raw_buffer[dev->cur_buf][0x000f] > 0x02)) { cdrom_log(dev->log, "[%s] Unknown mode: %02X\n", cdrom_req_modes[cdrom_sector_type], - dev->raw_buffer[0x000f]); + dev->raw_buffer[dev->cur_buf][0x000f]); ret = 0; } else if (mode2) { - if (dev->raw_buffer[0x000f] == 0x01) + if (dev->raw_buffer[dev->cur_buf][0x000f] == 0x01) /* Use Mode 1, since evidently specification-violating discs exist. */ mode2 = 0; - else if (dev->raw_buffer[0x0012] != - dev->raw_buffer[0x0016]) { + else if (dev->raw_buffer[dev->cur_buf][0x0012] != + dev->raw_buffer[dev->cur_buf][0x0016]) { cdrom_log(dev->log, "[%s] XA Mode 2 sector with " "malformed sub-header\n", cdrom_req_modes[cdrom_sector_type]); ret = 0; } else - form = ((dev->raw_buffer[0x0012] & 0x20) >> 5) + 1; - } else if (dev->raw_buffer[0x000f] == 0x02) + form = ((dev->raw_buffer[dev->cur_buf][0x0012] & + 0x20) >> 5) + 1; + } else if (dev->raw_buffer[dev->cur_buf][0x000f] == 0x02) mode2 = 1; if (ret > 0) { @@ -2281,7 +2432,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int } if (ret > 0) { - process_ecc_and_subch(dev, cdrom_sector_flags, b); + process_c2_and_subch(dev, cdrom_sector_flags, b); *len = dev->cdrom_sector_size; } } @@ -2617,7 +2768,7 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) if (track->adr_ctl & 0x04) { ret = read_data(dev, start); - mode = dev->raw_buffer[3]; + mode = dev->raw_buffer[dev->cur_buf][3]; } } else if (track->point != 0xa2) start = 0x00000000; @@ -2641,57 +2792,22 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer) return ret; } -int -cdrom_is_empty(const uint8_t id) +uint8_t +cdrom_get_current_mode(cdrom_t *dev) { - const cdrom_t *dev = &cdrom[id]; - int ret = 0; + if (dev->cached_sector == -1) + (void) read_data(dev, dev->seek_pos); + else + (void) read_data(dev, dev->cached_sector); - /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ - if (strlen(dev->image_path) == 0) - /* Switch from empty to empty. Do nothing. */ - ret = 1; - - return ret; + return dev->raw_buffer[dev->cur_buf][3]; } -#ifdef ENABLE_CDROM_LOG -static void -cdrom_toc_dump(cdrom_t *dev) -{ - uint8_t b[65536] = { 0 }; - int len = cdrom_read_toc(dev, b, CD_TOC_RAW, 0, 0, 65536); - const char *fn2 = "d:\\86boxnew\\toc_cue.dmp"; - FILE * f = fopen(fn2, "wb"); - fwrite(b, 1, len, f); - fflush(f); - fclose(f); - cdrom_log(dev->log, "Written TOC of %i bytes to %s\n", len, fn2); - - memset(b, 0x00, 65536); - len = cdrom_read_toc(dev, b, CD_TOC_NORMAL, 0, 0, 65536); - fn2 = "d:\\86boxnew\\toc_cue_cooked.dmp"; - f = fopen(fn2, "wb"); - fwrite(b, 1, len, f); - fflush(f); - fclose(f); - cdrom_log(dev->log, "Written cooked TOC of %i bytes to %s\n", len, fn2); - - memset(b, 0x00, 65536); - len = cdrom_read_toc(dev, b, CD_TOC_SESSION, 0, 0, 65536); - fn2 = "d:\\86boxnew\\toc_cue_session.dmp"; - f = fopen(fn2, "wb"); - fwrite(b, 1, len, f); - fflush(f); - fclose(f); - cdrom_log(dev->log, "Written session TOC of %i bytes to %s\n", len, fn2); -} -#endif - void cdrom_set_empty(cdrom_t *dev) { dev->cd_status = CD_STATUS_EMPTY; + dev->cached_sector = -1; } void @@ -2714,6 +2830,7 @@ cdrom_update_status(cdrom_t *dev) dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED : CD_STATUS_DATA_ONLY; + dev->cached_sector = -1; dev->cdrom_capacity = dev->ops->get_last_block(dev->local); if (dev->cd_status != CD_STATUS_EMPTY) { @@ -2744,6 +2861,8 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) else dev->local = image_open(dev, dev->image_path); + dev->cached_sector = -1; + if (dev->local == NULL) { dev->ops = NULL; dev->image_path[0] = 0; @@ -2790,6 +2909,9 @@ cdrom_global_init(void) { /* Clear the global data. */ memset(cdrom, 0x00, sizeof(cdrom)); + + for (uint8_t i = 0; i < CDROM_NUM; i++) + cdrom[i].cached_sector = -1; } void @@ -2799,11 +2921,26 @@ cdrom_hard_reset(void) cdrom_t *dev = &cdrom[i]; if (dev->bus_type) { - dev->id = i; + dev->id = i; - dev->is_early = cdrom_is_early(dev->type); - dev->is_nec = (dev->bus_type == CDROM_BUS_SCSI) && - !strcmp(cdrom_drive_types[dev->type].vendor, "NEC"); + const char *vendor = cdrom_drive_types[dev->type].vendor; + + dev->is_early = cdrom_is_early(dev->type); + dev->is_bcd = !strcmp(vendor, "NEC"); + dev->is_nec = (dev->bus_type == CDROM_BUS_SCSI) && + !strcmp(vendor, "NEC"); + dev->is_chinon = !strcmp(vendor, "CHINON"); + dev->is_pioneer = !strcmp(vendor, "PIONEER"); + dev->is_plextor = !strcmp(vendor, "PLEXTOR"); + dev->is_sony = (dev->bus_type == CDROM_BUS_SCSI) && + (!strcmp(vendor, "DEC") || + !strcmp(vendor, "ShinaKen") || + !strcmp(vendor, "SONY") || + !strcmp(vendor, "TEXEL")); + dev->is_toshiba = !strcmp(vendor, "TOSHIBA"); + + dev->c2_first = !strcmp(vendor, "NEC") || + !strcmp(vendor, "PLEXTOR"); cdrom_drive_reset(dev); @@ -2824,7 +2961,8 @@ cdrom_hard_reset(void) break; } - dev->cd_status = CD_STATUS_EMPTY; + dev->cd_status = CD_STATUS_EMPTY; + dev->cached_sector = -1; if (strlen(dev->image_path) > 0) { #ifdef _WIN32 @@ -2889,6 +3027,8 @@ cdrom_exit(const uint8_t id) strcpy(dev->prev_image_path, dev->image_path); + dev->cached_sector = -1; + if (dev->ops) { cdrom_unload(dev); @@ -2901,6 +3041,20 @@ cdrom_exit(const uint8_t id) cdrom_insert(id); } +int +cdrom_is_empty(const uint8_t id) +{ + const cdrom_t *dev = &cdrom[id]; + int ret = 0; + + /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ + if (strlen(dev->image_path) == 0) + /* Switch from empty to empty. Do nothing. */ + ret = 1; + + return ret; +} + /* The mechanics of ejecting a CD-ROM from a drive. */ void cdrom_eject(const uint8_t id) diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 271a290cb..519afaa4c 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -409,7 +409,7 @@ image_get_track_and_index(const cd_image_t *img, const uint32_t sector, for (int i = 0; i < img->tracks_num; i++) { track_t *ct = &(img->tracks[i]); - for (int j = 0; j < 3; j++) { + if ((ct->point >= 1) && (ct->point <= 99)) for (int j = 0; j < 3; j++) { track_index_t *ci = &(ct->idx[j]); if ((ci->type >= INDEX_ZERO) && (ci->length != 0ULL) && ((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) { diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 3683c8671..e367f73b0 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -241,6 +241,7 @@ int ide_qua_enabled = 0; static void ide_atapi_callback(ide_t *ide); static void ide_callback(void *priv); +#define ENABLE_IDE_LOG 1 #ifdef ENABLE_IDE_LOG int ide_do_log = ENABLE_IDE_LOG; @@ -1028,9 +1029,8 @@ ide_atapi_command_bus(ide_t *ide) static void ide_atapi_callback(ide_t *ide) { - int out; - int ret = 0; - ide_bm_t *bm = ide_boards[ide->board]->bm; + static int ret = 0; + ide_bm_t *bm = ide_boards[ide->board]->bm; #ifdef ENABLE_IDE_LOG char *phases[7] = { "Idle", "Command", "Data in", "Data out", "Data in DMA", "Data out DMA", "Complete" }; @@ -1056,14 +1056,17 @@ ide_atapi_callback(ide_t *ide) switch (ide->sc->packet_status) { default: + ret = 0; break; case PHASE_IDLE: + ret = 0; ide->tf->pos = 0; ide->tf->phase = 1; ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); break; case PHASE_COMMAND: + ret = 1; ide->tf->atastat = BUSY_STAT | (ide->tf->atastat & ERR_STAT); if (ide->packet_command) { ide->packet_command(ide->sc, ide->sc->atapi_cdb); @@ -1073,6 +1076,7 @@ ide_atapi_callback(ide_t *ide) break; case PHASE_COMPLETE: case PHASE_ERROR: + ret = 0; ide->tf->atastat = READY_STAT; if (ide->sc->packet_status == PHASE_ERROR) ide->tf->atastat |= ERR_STAT; @@ -1082,19 +1086,30 @@ ide_atapi_callback(ide_t *ide) break; case PHASE_DATA_IN: case PHASE_DATA_OUT: + ret = 0; ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); ide->tf->phase = !(ide->sc->packet_status & 0x01) << 1; ide_irq_raise(ide); break; case PHASE_DATA_IN_DMA: - case PHASE_DATA_OUT_DMA: - out = (ide->sc->packet_status & 0x01); - if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { - ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, bm->priv); - } - /* Else, DMA command without a bus master, ret = 0 (default). */ + if (ide->sc->block_len == 0) + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, bm->priv); + else { + ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos - + ide->sc->block_len, ide->sc->block_len, + 0, bm->priv); + + if (ret == 1) { + if (ide->sc->sector_len == 0) + ret = 3; + else if (ide->read != NULL) + ide->read(ide->sc); + } + } + } else + ret = 0; switch (ret) { default: @@ -1103,18 +1118,69 @@ ide_atapi_callback(ide_t *ide) if (ide->bus_master_error) ide->bus_master_error(ide->sc); break; - case 1: - if (out && ide->phase_data_out) - (void) ide->phase_data_out(ide->sc); - else if (!out && ide->command_stop) - ide->command_stop(ide->sc); + case 2: + ide_atapi_command_bus(ide); + break; + case 3: + /* Reached EOT - terminate the command as there's nothing + more to transfer. */ + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + if (ide->command_stop != NULL) + ide->command_stop(ide->sc); + fallthrough; + case 1: + if ((ide->sc->packet_status == PHASE_COMPLETE) && + (ide->sc->callback == 0.0)) ide_atapi_callback(ide); break; + } + break; + case PHASE_DATA_OUT_DMA: + if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && + (bm != NULL) && bm->dma) { + if (ide->sc->block_len == 0) + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 1, bm->priv); + else { + ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos, + ide->sc->block_len, 1, bm->priv); + + if (ret & 1) { + if (ide->write != NULL) + ide->write(ide->sc); + + if ((ret == 1) && (ide->sc->sector_len == 0)) + ret = 3; + } + } + } else + ret = 0; + + switch (ret) { + default: + break; + case 0: + if (ide->bus_master_error) + ide->bus_master_error(ide->sc); + break; case 2: ide_atapi_command_bus(ide); break; + case 3: + /* Reached EOT - terminate the command as there's nothing + more to transfer. */ + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; + + if (ide->phase_data_out != NULL) + (void) ide->phase_data_out(ide->sc); + fallthrough; + case 1: + if ((ide->sc->packet_status == PHASE_COMPLETE) && + (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); + break; } break; } @@ -1134,22 +1200,37 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read"); ide->tf->pos = dev->request_pos = 0; - if (out && ide->phase_data_out) - ide->phase_data_out(dev); - else if (!out && ide->command_stop) - ide->command_stop(dev); - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) - ide_atapi_callback(ide); + if (dev->block_len != 0) { + if (out && (ide->write != NULL)) + ide->write(dev); + else if (!out && (dev->sector_len != 0) && (ide->read != NULL)) + ide->read(dev); + } + + if ((dev->block_len == 0) || (dev->sector_len == 0)) { + if (out && (ide->phase_data_out != NULL)) + ide->phase_data_out(dev); + else if (!out && (ide->command_stop != NULL)) + ide->command_stop(dev); + + if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); + } } else { ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos, out ? "written" : "read", dev->packet_len - ide->tf->pos); - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ + /* + If less than (packet length) bytes are remaining, update packet length + accordingly. + */ if ((dev->packet_len - ide->tf->pos) < (dev->max_transfer_len)) { dev->max_transfer_len = dev->packet_len - ide->tf->pos; - /* Also update the request length so the host knows how many bytes to transfer. */ + /* + Also update the request length so the host knows how many bytes to + transfer. + */ ide->tf->request_length = dev->max_transfer_len; } ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, @@ -1157,10 +1238,20 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) dev->packet_status = PHASE_DATA_IN | out; + if (dev->block_len != 0) { + if (out && (ide->write != NULL)) + ide->write(dev); + else if (!out && (dev->sector_len != 0) && (ide->read != NULL)) + ide->read(dev); + } + ide->tf->atastat = BSY_STAT; ide->tf->phase = 1; - ide_atapi_callback(ide); - ide_set_callback(ide, 0.0); + + if ((dev->block_len == 0) || (dev->sector_len == 0)) { + ide_atapi_callback(ide); + ide_set_callback(ide, 0.0); + } dev->request_pos = 0; } @@ -1179,19 +1270,26 @@ ide_atapi_packet_read(ide_t *ide) bufferw = (uint16_t *) dev->temp_buffer; - /* Make sure we return a 0 and don't attempt to read from the buffer if + /* + Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ + (which is 1 sector = 2048 bytes). + */ ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0; ide->tf->pos += 2; dev->request_pos += 2; - if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { + if ((dev->request_pos >= dev->max_transfer_len) || + (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ ide_atapi_pio_request(ide, 0); - } + } else if ((dev->block_len != 0) && + (dev->sector_len != 0) && + ((dev->request_pos % dev->block_len) == 0) && + (ide->read != NULL)) + ide->read(dev); } return ret; @@ -1221,10 +1319,14 @@ ide_atapi_packet_write(ide_t *ide, const uint16_t val) dev->request_pos += 2; if (dev->packet_status == PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { + if ((dev->request_pos >= dev->max_transfer_len) || + (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ ide_atapi_pio_request(ide, 1); - } + } else if ((dev->block_len != 0) && + ((dev->request_pos % dev->block_len) == 0) && + (ide->write != NULL)) + ide->write(dev); } else if (dev->packet_status == PHASE_IDLE) { if (ide->tf->pos >= 12) { ide->tf->pos = 0; @@ -1287,7 +1389,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ide = ide_drives[ch]; #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) - ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); + ide_log("[%04X:%08X] ide_writew(%04X, %04X, %08X)\n", CS, cpu_state.pc, addr, val, priv); #endif addr &= 0x7; @@ -1321,7 +1423,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ide = ide_drives[ch]; #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) - ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); + ide_log("[%04X:%08X] ide_writel(%04X, %08X, %08X)\n", CS, cpu_state.pc, addr, val, priv); #endif addr &= 0x7; @@ -1371,9 +1473,9 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_write_devctl(%04X, %02X, %08X)\n", addr, val, priv); + ide_log("[%04X:%08X] ide_write_devctl(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); - if ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE)) + if ((addr & 0x0001) || ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE))) return; dev->diag = 0; @@ -1481,7 +1583,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv); + ide_log("[%04X:%08X] ide_writeb(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); addr &= 0x7; @@ -1831,7 +1933,7 @@ ide_read_data(ide_t *ide) const uint16_t *idebufferw = ide->buffer; uint16_t ret = 0x0000; -#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) +#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 3) ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ide->channel, ide->board, ide->type); #endif @@ -2010,7 +2112,7 @@ ide_readb(uint16_t addr, void *priv) break; } - ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret); + ide_log("[%04X:%08X] ide_readb(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); return ret; } @@ -2022,12 +2124,14 @@ ide_read_alt_status(UNUSED(const uint16_t addr), void *priv) const int ch = dev->cur_dev; ide_t * ide = ide_drives[ch]; + uint8_t ret = 0xff; /* Per the Seagate ATA-3 specification: Reading the alternate status does *NOT* clear the IRQ. */ - const uint8_t ret = ide_status(ide, ide_drives[ch ^ 1], ch); + if (!(addr & 0x0001)) + ret = ide_status(ide, ide_drives[ch ^ 1], ch); - ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, ret); + ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); return ret; } @@ -2053,7 +2157,7 @@ ide_readw(uint16_t addr, void *priv) } #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) - ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); + ide_log("[%04X:%08X] ide_readw(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret); #endif return ret; } @@ -2084,7 +2188,7 @@ ide_readl(uint16_t addr, void *priv) } #if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2) - ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); + ide_log("[%04X:%08X] ide_readl(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret); #endif return ret; } @@ -2270,7 +2374,7 @@ ide_callback(void *priv) ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide_set_callback(ide, 6.0 * IDE_TIME); return; - } else if (ret == 1) { + } else if (ret & 1) { /* DMA successful */ ide_log("IDE %i: DMA read successful\n", ide->channel); @@ -2379,7 +2483,7 @@ ide_callback(void *priv) ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide_set_callback(ide, 6.0 * IDE_TIME); return; - } else if (ret == 1) { + } else if (ret & 1) { /* DMA successful */ ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); @@ -2637,7 +2741,7 @@ ide_handlers(uint8_t board, int set) } if (ide_boards[board]->base[1]) { - io_handler(set, ide_boards[board]->base[1], 1, + io_handler(set, ide_boards[board]->base[1], 2, ide_read_alt_status, NULL, NULL, ide_write_devctl, NULL, NULL, ide_boards[board]); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 73dc5f36b..2cc1fe72e 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -375,7 +375,7 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv) } else if (dev->eot) { sff_log("Regular EOT\n"); dev->status &= ~3; - return 1; /* We have regularly reached EOT - clear status and break. */ + return 3; /* We have regularly reached EOT - clear status and break. */ } else { /* We have more to transfer and there are blocks left, get next block. */ sff_bus_master_next_addr(dev); diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index 7c028d7d6..c6347fc3e 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -28,8 +28,9 @@ #define CD_STATUS_PLAYING 5 #define CD_STATUS_STOPPED 6 #define CD_STATUS_PLAYING_COMPLETED 7 -#define CD_STATUS_HAS_AUDIO 4 -#define CD_STATUS_MASK 7 +#define CD_STATUS_HOLD 8 +#define CD_STATUS_HAS_AUDIO 0xc +#define CD_STATUS_MASK 0xf /* Medium changed flag. */ #define CD_STATUS_TRANSITION 0x40 @@ -50,8 +51,6 @@ #define CD_IMAGE_HISTORY 10 -#define BUF_SIZE 32768 - #define CDROM_IMAGE 200 /* This is so that if/when this is changed to something else, @@ -63,6 +62,8 @@ #define RAW_SECTOR_SIZE 2352 #define COOKED_SECTOR_SIZE 2048 +#define CD_BUF_SIZE (16 * RAW_SECTOR_SIZE) + #define DATA_TRACK 0x14 #define AUDIO_TRACK 0x10 @@ -105,9 +106,9 @@ enum { #define CDV EMU_VERSION_EX static const struct cdrom_drive_types_s { - const char vendor[9]; - const char model[17]; - const char revision[5]; + const char * vendor; + const char * model; + const char * revision; const char * internal_name; const int bus_type; /* SCSI standard for SCSI (or both) devices, early for IDE. */ @@ -298,9 +299,7 @@ typedef struct cdrom { void * priv; char image_path[1024]; - char prev_image_path[1024]; - - char * image_history[CD_IMAGE_HISTORY]; + char prev_image_path[1280]; uint32_t sound_on; uint32_t cdrom_capacity; @@ -310,18 +309,21 @@ typedef struct cdrom { uint32_t type; uint32_t sector_size; - int cd_buflen; - int audio_op; - int audio_muted_soft; - int sony_msf; - int real_speed; - int is_early; - int is_nec; - uint32_t inv_field; + int32_t cached_sector; + int32_t cd_buflen; + int32_t sony_msf; + int32_t real_speed; + int32_t is_early; + int32_t is_nec; + int32_t is_bcd; + + int32_t cdrom_sector_size; const cdrom_ops_t *ops; + char * image_history[CD_IMAGE_HISTORY]; + void * local; void * log; @@ -330,22 +332,26 @@ typedef struct cdrom { uint32_t (*get_volume)(void *p, int channel); uint32_t (*get_channel)(void *p, int channel); - int16_t cd_buffer[BUF_SIZE]; + int16_t cd_buffer[CD_BUF_SIZE]; uint8_t subch_buffer[96]; - int cdrom_sector_size; - /* Needs some extra breathing space in case of overflows. */ - uint8_t raw_buffer[4096]; + uint8_t raw_buffer[2][4096]; uint8_t extra_buffer[296]; + + int32_t is_chinon; + int32_t is_pioneer; + int32_t is_plextor; + int32_t is_sony; + int32_t is_toshiba; + + int32_t c2_first; + int32_t cur_buf; } cdrom_t; extern cdrom_t cdrom[CDROM_NUM]; -/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: - there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start - 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 __inline int @@ -366,8 +372,6 @@ extern char *cdrom_get_revision(const int type); extern int cdrom_get_scsi_std(const int type); extern int cdrom_is_early(const int type); extern int cdrom_is_generic(const int type); -extern int cdrom_has_date(const int type); -extern int cdrom_is_sony(const int type); extern int cdrom_is_caddy(const int type); extern int cdrom_get_speed(const int type); extern int cdrom_get_inquiry_len(const int type); @@ -384,6 +388,7 @@ extern void cdrom_set_type(const int model, const int type); extern int cdrom_get_type(const int model); extern int cdrom_lba_to_msf_accurate(const int lba); +extern void cdrom_interleave_subch(uint8_t *d, const uint8_t *s); extern double cdrom_seek_time(const cdrom_t *dev); extern void cdrom_stop(cdrom_t *dev); extern void cdrom_seek(cdrom_t *dev, const uint32_t pos, const uint8_t vendor_type); @@ -396,7 +401,7 @@ extern uint8_t cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t playbit); extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos); extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type); -extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type); +extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos); extern void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume); extern uint8_t cdrom_get_current_status(const cdrom_t *dev); @@ -424,6 +429,7 @@ extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_ uint8_t *buffer, uint32_t *info); extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer); extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer); +extern uint8_t cdrom_get_current_mode(cdrom_t *dev); extern void cdrom_set_empty(cdrom_t *dev); extern void cdrom_update_status(cdrom_t *dev); extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert); diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 1c2ec5203..6902ffdfd 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -118,16 +118,6 @@ enum { #define BIOS_INTERLEAVED_INVERT 8 #define BIOS_HIGH_BIT_INVERT 16 -#define device_common_config_t \ - const char *name; \ - const char *description; \ - int type; \ - const char *default_string; \ - int default_int; \ - const char *file_filter; \ - const device_config_spinner_t spinner; \ - const device_config_selection_t selection[32] - typedef struct device_config_selection_t { const char *description; int value; @@ -139,10 +129,6 @@ typedef struct device_config_spinner_t { int16_t step; } device_config_spinner_t; -typedef struct _device_dep_config_ { - device_common_config_t; -} device_dep_config_t; - typedef struct device_config_bios_t { const char *name; const char *internal_name; @@ -153,15 +139,18 @@ typedef struct device_config_bios_t { void *dev1; void *dev2; const char *files[9]; - /* Configuration options that depend on the device variant. - To prevent excessive nesting, there is no CONFIG_BIOS - option a dep_config struct */ - const device_dep_config_t *dep_config; } device_config_bios_t; typedef struct _device_config_ { - device_common_config_t; - const device_config_bios_t bios[32]; + const char *name; + const char *description; + int type; + const char *default_string; + int default_int; + const char *file_filter; + const device_config_spinner_t spinner; + const device_config_selection_t selection[32]; + const device_config_bios_t bios[32]; } device_config_t; typedef struct _device_ { diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 6af4d92e6..4e4ea4e5b 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -133,6 +133,8 @@ typedef struct ide_s { uint8_t (*phase_data_out)(scsi_common_t *sc); void (*command_stop)(scsi_common_t *sc); void (*bus_master_error)(scsi_common_t *sc); + void (*read)(scsi_common_t *sc); + void (*write)(scsi_common_t *sc); #else void * get_max; void * get_timings; diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index b80c21c13..eda4396ef 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -138,55 +138,63 @@ typedef struct hdd_zone_t { /* Define the virtual Hard Disk. */ typedef struct hard_disk_t { - uint8_t id; + uint8_t id; + union { - uint8_t channel; /* Needed for Settings to reduce the number of if's */ + /* Needed for Settings to reduce the number of if's */ + uint8_t channel; - uint8_t mfm_channel; /* Should rename and/or unionize */ - uint8_t esdi_channel; - uint8_t xta_channel; - uint8_t ide_channel; - uint8_t scsi_id; + uint8_t mfm_channel; + uint8_t esdi_channel; + uint8_t xta_channel; + uint8_t ide_channel; + uint8_t scsi_id; }; - uint8_t bus_type; - uint8_t bus_mode; /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - uint8_t wp; /* Disk has been mounted READ-ONLY */ - uint8_t pad; - uint8_t pad0; - void *priv; + uint8_t bus_type; + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + uint8_t wp; /* Disk has been mounted + READ-ONLY */ + uint8_t pad; + uint8_t pad0; - char fn[1024]; /* Name of current image file */ - char vhd_parent[1041]; /* Differential VHD parent file */ + void * priv; - uint32_t seek_pos; - uint32_t seek_len; - uint32_t base; - uint32_t spt; - uint32_t hpc; /* Physical geometry parameters */ - uint32_t tracks; - const char *model; + char fn[1024]; /* Name of current image file */ + /* Differential VHD parent file */ + char vhd_parent[1280]; - hdd_zone_t zones[HDD_MAX_ZONES]; - uint32_t num_zones; - hdd_cache_t cache; - uint32_t phy_cyl; - uint32_t phy_heads; - uint32_t rpm; - uint8_t max_multiple_block; + uint32_t seek_pos; + uint32_t seek_len; + uint32_t base; + uint32_t spt; /* Physical geometry parameters */ + uint32_t hpc; + uint32_t tracks; + uint32_t speed_preset; - uint32_t cur_cylinder; - uint32_t cur_track; - uint32_t cur_addr; + uint32_t num_zones; + uint32_t phy_cyl; + uint32_t phy_heads; + uint32_t rpm; + uint32_t cur_cylinder; + uint32_t cur_track; + uint32_t cur_addr; + uint32_t vhd_blocksize; - uint32_t speed_preset; - uint32_t vhd_blocksize; + uint8_t max_multiple_block; + uint8_t pad1[3]; - double avg_rotation_lat_usec; - double full_stroke_usec; - double head_switch_usec; - double cyl_switch_usec; + const char * model; + + hdd_zone_t zones[HDD_MAX_ZONES]; + + hdd_cache_t cache; + + double avg_rotation_lat_usec; + double full_stroke_usec; + double head_switch_usec; + double cyl_switch_usec; } hard_disk_t; extern hard_disk_t hdd[HDD_NUM]; diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index 1df16c3fe..e09515b10 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -51,10 +51,10 @@ static const mo_type_t mo_types[KNOWN_MO_TYPES] = { }; typedef struct mo_drive_type_t { - const char vendor[9]; - const char model[16]; - const char revision[5]; - int8_t supported_media[KNOWN_MO_TYPES]; + const char *vendor; + const char *model; + const char *revision; + int8_t supported_media[KNOWN_MO_TYPES]; } mo_drive_type_t; #define KNOWN_MO_DRIVE_TYPES 22 @@ -161,6 +161,7 @@ typedef struct mo_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; + uint32_t block_len; double callback; diff --git a/src/include/86box/scsi_cdrom.h b/src/include/86box/scsi_cdrom.h index bc2d4c8bd..7bb39d9db 100644 --- a/src/include/86box/scsi_cdrom.h +++ b/src/include/86box/scsi_cdrom.h @@ -54,18 +54,24 @@ typedef struct scsi_cdrom_t { int do_page_save; int unit_attention; int request_pos; - int old_len; - int media_status; + int wait; + int buffer_pos; uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; + uint32_t block_len; double callback; - int is_sony; - int use_cdb_9; + uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen); + int use_cdb_9; + int was_cached; + int toc_cached; + int media_access; + + uint8_t vendor_type; uint8_t ven_cmd_is_data[256]; mode_sense_pages_t ms_drive_status_pages_saved; @@ -74,8 +80,6 @@ typedef struct scsi_cdrom_t { mode_sense_pages_t ms_pages_default; mode_sense_pages_t ms_pages_changeable; - - uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen); } scsi_cdrom_t; #endif diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index ffe042481..62da8b7dc 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -110,39 +110,40 @@ #define GPCMD_MECHANISM_STATUS 0xbd #define GPCMD_READ_CD 0xbe #define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */ -#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */ #define GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA 0xc0 /* Toshiba Vendor Unique command */ -#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */ +#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */ #define GPCMD_MAGAZINE_EJECT_PIONEER 0xc0 /* Pioneer Vendor Unique command */ +#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */ #define GPCMD_PLAY_AUDIO_TOSHIBA 0xc1 /* Toshiba Vendor Unique command */ -#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */ #define GPCMD_READ_TOC_PIONEER 0xc1 /* Pioneer Vendor Unique command */ +#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */ #define GPCMD_PAUSE_RESUME_ALT 0xc2 #define GPCMD_READ_SUBCHANNEL_MATSUSHITA 0xc2 /* Matsushita Vendor Unique command */ +#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */ #define GPCMD_READ_SUBCHANNEL_SONY 0xc2 /* Sony Vendor Unique command */ #define GPCMD_STILL_TOSHIBA 0xc2 /* Toshiba Vendor Unique command */ -#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */ #define GPCMD_READ_TOC_MATSUSHITA 0xc3 /* Matsushita Vendor Unique command */ #define GPCMD_READ_HEADER_SONY 0xc3 /* Sony Vendor Unique command */ #define GPCMD_SET_STOP_TIME_TOSHIBA 0xc3 /* Toshiba Vendor Unique command */ -#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */ -#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */ #define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */ +#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */ +#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita 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 */ +#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */ #define GPCMD_PLAY_AUDIO_MSF_MATSUSHITA 0xc7 /* Matsushita Vendor Unique command*/ #define GPCMD_PLAY_MSF_SONY 0xc7 /* Sony Vendor Unique command*/ #define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */ -#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */ -#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */ #define GPCMD_AUDIO_TRACK_SEARCH_PIONEER 0xc8 /* Pioneer Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */ +#define GPCMD_READ_CDROM_MODE_TOSHIBA 0xc8 /* Toshiba Vendor Unique command */ +#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */ #define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA 0xc9 /* Matsushita Vendor Unique command */ #define GPCMD_PLAYBACK_CONTROL_SONY 0xc9 /* Sony Vendor Unique command */ -#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */ #define GPCMD_PAUSE_PIONEER 0xca /* Pioneer Vendor Unique command */ #define GPCMD_PAUSE_RESUME_MATSUSHITA 0xcb /* Matsushita Vendor Unique command */ #define GPCMD_STOP_PIONEER 0xcb /* Pioneer Vendor Unique command */ @@ -151,8 +152,8 @@ #define GPCMD_READ_CD_MSF_OLD 0xd5 /* Should be equivalent to 0xb9 */ #define GPCMD_AUDIO_TRACK_SEARCH_NEC 0xd8 /* NEC Vendor Unique command */ #define GPCMD_PLAY_AUDIO_NEC 0xd9 /* NEC Vendor Unique command */ -#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */ #define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ +#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */ #define GPCMD_SET_STOP_TIME_NEC 0xdb /* NEC Vendor Unique command */ #define GPCMD_CADDY_EJECT_NEC 0xdc /* NEC Vendor Unique command */ #define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC 0xdd /* NEC Vendor Unique command */ @@ -409,12 +410,13 @@ typedef struct scsi_common_s { int do_page_save; int unit_attention; int request_pos; - int old_len; - int media_status; + int wait; + int buffer_pos; uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; + uint32_t block_len; double callback; diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index 7099b836a..293cc35e6 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -53,6 +53,7 @@ typedef struct scsi_disk_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; + uint32_t block_len; double callback; diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 06c6e8485..443ab1327 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -108,6 +108,7 @@ typedef struct zip_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; + uint32_t block_len; double callback; diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 13e0ec9a7..272b389c5 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -65,6 +65,7 @@ extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); #include "ui_qt_mainwindow.h" bool windows_is_light_theme() { + return 0; // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application // The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 621cf0b76..3d9ecefd5 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -91,6 +91,20 @@ ioctl_open_handle(ioctl_t *ioctl) ioctl_log(ioctl->log, "handle=%p, error=%x\n", ioctl->handle, (unsigned int) GetLastError()); + if (ioctl->handle != INVALID_HANDLE_VALUE) { + CDROM_SET_SPEED set_speed = { 0 }; + + set_speed.RequestType = CdromSetSpeed; + set_speed.ReadSpeed = 0xffff; + set_speed.WriteSpeed = 0xffff; + set_speed.RotationControl = CdromDefaultRotation; + + (void) DeviceIoControl(ioctl->handle, IOCTL_CDROM_SET_SPEED, + &set_speed, sizeof(set_speed), + NULL, 0, + 0, NULL); + } + return (ioctl->handle != INVALID_HANDLE_VALUE); } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 04c6532df..07590d5ae 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -15,6 +15,7 @@ */ #include #include +#define ENABLE_SCSI_CDROM_LOG 2 #ifdef ENABLE_SCSI_CDROM_LOG #include #endif @@ -110,6 +111,7 @@ uint8_t scsi_cdrom_command_flags[0x100] = { [0xbd] = IMPLEMENTED, [0xbe ... 0xbf] = IMPLEMENTED | CHECK_READY, [0xc0 ... 0xcd] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0xd5] = IMPLEMENTED | CHECK_READY, [0xd8 ... 0xde] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, [0xe0 ... 0xe1] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, [0xe3 ... 0xe9] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, @@ -303,15 +305,14 @@ scsi_cdrom_init(scsi_cdrom_t *dev) dev->tf->status = 0; dev->tf->pos = 0; dev->packet_status = PHASE_NONE; - scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; + scsi_cdrom_sense_key = scsi_cdrom_asc = + scsi_cdrom_ascq = dev->unit_attention = 0; scsi_cdrom_info = 0x00000000; dev->drv->cd_status &= ~CD_STATUS_TRANSITION; dev->drv->cur_speed = dev->drv->real_speed; scsi_cdrom_mode_sense_load(dev); - const char *vendor = cdrom_get_vendor(dev->drv->type); - - if ((dev->drv->bus_type == CDROM_BUS_SCSI) && !strcmp(vendor, "PIONEER")) + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && dev->drv->is_pioneer) scsi_cdrom_drive_status_load(dev); } } @@ -339,7 +340,7 @@ scsi_cdrom_get_channel(void *priv, const int channel) uint32_t ret = channel + 1; if (dev != NULL) - ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; + ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8] & 0x0f; return ret; } @@ -530,7 +531,8 @@ scsi_cdrom_mode_sense(const scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, buf[pos++] = ((dev->drv->cur_speed * 176) & 0xff); else buf[pos++] = ((dev->drv->cur_speed * 176) >> 8); - } else if (dev->is_sony && (i == GPMODE_CDROM_AUDIO_PAGE_SONY) && + } else if (dev->drv->is_sony && + (i == GPMODE_CDROM_AUDIO_PAGE_SONY) && (j >= 6) && (j <= 13)) buf[pos++] = scsi_cdrom_mode_sense_read(dev, pgctl, GPMODE_CDROM_AUDIO_PAGE, 2 + j); @@ -559,13 +561,21 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, const int block_len matches the block length. */ switch (dev->current_cdb[0]) { + case 0xbc: + if (!dev->drv->is_early) { + dev->packet_len = len; + break; + } + fallthrough; case 0x08: case 0x28: case 0xa8: + case 0xb8: case 0xb9: case 0xbe: + case 0xd5: /* Round it to the nearest (block length) bytes. */ - if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { + if (dev->current_cdb[0] >= 0xb8) { /* READ CD MSF and READ CD: Round the request length to the sector size - the device must ensure that a media access comand does not DRQ in the middle @@ -601,10 +611,11 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, const int block_len break; } } + dev->requested_blocks = 1; fallthrough; default: - dev->packet_len = len; + dev->packet_len = len; break; } /* @@ -649,16 +660,10 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) } static void -scsi_cdrom_command_common(scsi_cdrom_t *dev) +scsi_cdrom_set_period(scsi_cdrom_t *dev) { const uint8_t cmd = dev->current_cdb[0]; - /* MAP: BUSY_STAT, no DRQ, phase 1. */ - dev->tf->status = BUSY_STAT; - dev->tf->phase = 1; - dev->tf->pos = 0; - dev->callback = 0; - scsi_cdrom_log(dev->log, "Current speed: %ix\n", dev->drv->cur_speed); if (dev->packet_status == PHASE_COMPLETE) @@ -667,91 +672,38 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) double bytes_per_second; double period; - switch (cmd) { - case GPCMD_REZERO_UNIT: - case 0x0b: - case 0x2b: - /* Seek time is in us. */ - period = cdrom_seek_time(dev->drv); - scsi_cdrom_log(dev->log, "Seek period: %" PRIu64 " us\n", - (uint64_t) period); - dev->callback += period; + if (dev->was_cached != -1) { + if (dev->was_cached) { + dev->callback += 512.0; scsi_cdrom_set_callback(dev); return; - case 0x43: - dev->drv->seek_diff = dev->drv->seek_pos + 150; - dev->drv->seek_pos = 0; - fallthrough; - case 0x08: - case 0x28: - case 0x42: case 0x44: - case 0xa8: - /* Seek time is in us. */ - period = cdrom_seek_time(dev->drv); - scsi_cdrom_log(dev->log, "Seek period: %" PRIu64 " us\n", - (uint64_t) period); - scsi_cdrom_log(dev->log, "Seek period: %" PRIu64 " us, speed: %" - PRIu64 " bytes per second, should be: %" - PRIu64 " bytes per second\n", - (uint64_t) period, (uint64_t) (1000000.0 / period), - (uint64_t) (176400.0 * (double) dev->drv->cur_speed)); - dev->callback += period; - fallthrough; - case 0x25: - // case 0x42 ... 0x44: - case 0x51 ... 0x52: - case 0xad: - case 0xb8 ... 0xb9: - case 0xbe: - if (dev->current_cdb[0] == 0x42) - dev->callback += 40.0; - /* Account for seek time. */ - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - /* - TODO: This is a bit of a lie - the actual period is closer to - 75 * 2448 bytes per second, because the subchannel data - has to be read as well. - */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - case 0xc0 ... 0xc3: - case 0xc6 ... 0xc7: - case 0xdd ... 0xde: - if (dev->ven_cmd_is_data[cmd]) { - if (dev->current_cdb[0] == 0xc2) - dev->callback += 40.0; - /* Account for seek time. */ - /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - bytes_per_second = 176400.0; - bytes_per_second *= (double) dev->drv->cur_speed; - break; - } - fallthrough; - default: - bytes_per_second = scsi_cdrom_bus_speed(dev); - if (bytes_per_second == 0.0) { - dev->callback = -1; /* Speed depends on SCSI controller */ - return; - } - break; + } + + /* Seek time is in us. */ + period = cdrom_seek_time(dev->drv); + scsi_cdrom_log(dev->log, "Seek period: %" PRIu64 " us\n", + (uint64_t) period); + dev->callback += period; + + /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ + bytes_per_second = 176400.0; + bytes_per_second *= (double) dev->drv->cur_speed; + } else { + bytes_per_second = scsi_cdrom_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1; /* Speed depends on SCSI controller */ + return; + } } period = 1000000.0 / bytes_per_second; scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", (uint64_t) period); - switch (cmd) { - default: - period = period * (double) (dev->packet_len); - break; - case 0x42: case 0x44: - /* READ SUBCHANNEL or READ HEADER - period of 1 entire sector. */ - period = period * 2352.0; - break; - case 0x43: - /* READ TOC - period of 175 entire frames. */ - period = period * 150.0 * 2352.0; - break; + if (dev->was_cached == -1) + period *= (double) dev->packet_len; + else { + period *= ((double) dev->requested_blocks) * 2352.0; + pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, dev->requested_blocks); } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); @@ -760,6 +712,18 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) scsi_cdrom_set_callback(dev); } +static void +scsi_cdrom_command_common(scsi_cdrom_t *dev) +{ + /* MAP: BUSY_STAT, no DRQ, phase 1. */ + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; + dev->callback = 0; + + scsi_cdrom_set_period(dev); +} + static void scsi_cdrom_command_complete(scsi_cdrom_t *dev) { @@ -977,7 +941,7 @@ scsi_cdrom_invalid_lun(scsi_cdrom_t *dev, const uint8_t lun) static void scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev, const uint8_t opcode) { - scsi_cdrom_log(dev->log, "Illegal opcode\n"); + scsi_cdrom_log(dev->log, "Illegal opcode: %02X\n", opcode); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_ILLEGAL_OPCODE; scsi_cdrom_ascq = 0; @@ -988,7 +952,7 @@ scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev, const uint8_t opcode) static void scsi_cdrom_lba_out_of_range(scsi_cdrom_t *dev) { - scsi_cdrom_log(dev->log, "LBA out of range\n"); + scsi_cdrom_log(dev->log, "LBA out of range: %08X\n", dev->sector_pos); scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; scsi_cdrom_asc = ASC_LBA_OUT_OF_RANGE; scsi_cdrom_ascq = 0; @@ -1073,7 +1037,7 @@ scsi_cdrom_illegal_mode(scsi_cdrom_t *dev) static int scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int flags, - int32_t *len, const int vendor_type) + const int vendor_type) { int temp_len = 0; int ret = 0; @@ -1081,69 +1045,60 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int if (dev->drv->cd_status == CD_STATUS_EMPTY) scsi_cdrom_not_ready(dev); else { - const uint32_t cdsize = dev->drv->cdrom_capacity; - - if (dev->sector_pos >= cdsize) { - scsi_cdrom_log(dev->log, "Trying to read from beyond the end of " - "disc (%i >= %i)\n", dev->sector_pos, cdsize); + if (dev->sector_pos > dev->drv->cdrom_capacity) { scsi_cdrom_lba_out_of_range(dev); ret = -1; } else { - int data_pos = 0; + ret = cdrom_readsector_raw(dev->drv, dev->buffer + dev->buffer_pos, + dev->sector_pos, msf, type, + flags, &temp_len, vendor_type); - dev->old_len = 0; - *len = 0; + if (ret < 0) + scsi_cdrom_circ_error(dev); + else if (ret == 0) + scsi_cdrom_illegal_mode(dev); + else { + if (dev->block_len == 0xffffffff) + dev->block_len = temp_len; - ret = 1; + dev->sector_pos++; + dev->drv->seek_pos = dev->sector_pos; - for (int i = 0; i < dev->requested_blocks; i++) { - ret = cdrom_readsector_raw(dev->drv, dev->buffer + data_pos, - dev->sector_pos + i, msf, type, - flags, &temp_len, vendor_type); + dev->sector_len--; - data_pos += temp_len; - dev->old_len += temp_len; - - *len += temp_len; - - if (ret == 0) { - scsi_cdrom_illegal_mode(dev); - break; - } - - if (ret < 0) { - scsi_cdrom_circ_error(dev); - break; - } + pclog("Sector read to buffer position %08X\n", dev->buffer_pos); + dev->buffer_pos += temp_len; } } } + if ((ret < 1) || (dev->sector_len == 0)) + dev->wait = 0; + return ret; } static int -scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, const int vendor_type) +scsi_cdrom_read_blocks(scsi_cdrom_t *dev) { int ret = 1; int msf = 0; int type = dev->sector_type; int flags = dev->sector_flags; - /* Any of these commands stop the audio playing. */ - cdrom_stop(dev->drv); - switch (dev->current_cdb[0]) { case GPCMD_READ_CD_MSF_OLD: case GPCMD_READ_CD_MSF: msf = 1; fallthrough; + case GPCMD_PLAY_CD: case GPCMD_READ_CD_OLD: case GPCMD_READ_CD: type = (dev->current_cdb[1] >> 2) & 7; flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); break; case GPCMD_READ_HEADER: + case GPCMD_READ_HEADER_SONY: type = 0x00; flags = 0x20; break; @@ -1164,16 +1119,10 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, const int vendor_type) scsi_cdrom_log(dev->log, "Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - ret = scsi_cdrom_read_data(dev, msf, type, flags, len, vendor_type); + ret = scsi_cdrom_read_data(dev, msf, type, flags, dev->vendor_type); - scsi_cdrom_log(dev->log, "Read %i bytes of blocks (ret = %i)...\n", *len, ret); - } - - if ((ret > 0) && (dev->current_cdb[0] != GPCMD_READ_HEADER)) { - dev->sector_pos += dev->requested_blocks; - dev->drv->seek_pos = dev->sector_pos; - - dev->sector_len -= dev->requested_blocks; + scsi_cdrom_log(dev->log, "Read %i bytes of blocks (ret = %i)...\n", + dev->block_len, ret); } return ret; @@ -1214,7 +1163,7 @@ scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb) check for ready status but they do on Y vendor. Quite confusing I know. */ - if (!dev->is_sony || (cdb[0] != 0xc0)) + if (!dev->drv->is_sony || (cdb[0] != 0xc0)) ret = 1; } else if ((cdb[0] == GPCMD_READ_DVD_STRUCTURE) && (cdb[7] < 0xc0)) ret = 1; @@ -1317,12 +1266,6 @@ skip_ready_check: if (cdb[0] != GPCMD_REQUEST_SENSE) scsi_cdrom_sense_clear(dev, cdb[0]); - /* Next it's time for NOT READY. */ - if (ready) - dev->media_status = dev->unit_attention ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - else - dev->media_status = MEC_MEDIA_REMOVAL; - if (!ready && scsi_command_check_ready(dev, cdb)) { scsi_cdrom_log(dev->log, "Not ready (%02X)\n", cdb[0]); scsi_cdrom_not_ready(dev); @@ -1336,6 +1279,7 @@ skip_ready_check: static void scsi_cdrom_rezero(scsi_cdrom_t *dev) { + dev->drv->seek_diff = ABS(dev->sector_pos); dev->sector_pos = dev->sector_len = 0; cdrom_seek(dev->drv, 0, 0); } @@ -1388,6 +1332,10 @@ scsi_cdrom_update_sector_flags(scsi_cdrom_t *dev) dev->sector_type = 0x00; dev->sector_flags = 0x02f8; break; + case 2646: + dev->sector_type = 0x00; + dev->sector_flags = 0x00fa; + break; } return ret; @@ -1412,9 +1360,11 @@ scsi_cdrom_reset(scsi_common_t *sc) dev->drv->sector_size = 2048; (void) scsi_cdrom_update_sector_flags(dev); - scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; - scsi_cdrom_info = 0x00000000; - dev->drv->cd_status &= ~CD_STATUS_TRANSITION; + scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; + scsi_cdrom_info = 0x00000000; + dev->drv->cd_status &= ~CD_STATUS_TRANSITION; + dev->drv->cached_sector = -1; + dev->toc_cached = 0; } } @@ -1498,6 +1448,8 @@ scsi_cdrom_stop(const scsi_common_t *sc) const scsi_cdrom_t *dev = (const scsi_cdrom_t *) sc; cdrom_stop(dev->drv); + + ui_sb_update_icon(SB_CDROM | dev->id, 0); } static void @@ -1536,6 +1488,7 @@ scsi_cdrom_command_chinon(void *sc, const uint8_t *cdb, UNUSED(int32_t *BufLen)) scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_stop(sc); cdrom_eject(dev->id); + dev->toc_cached = 0; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; @@ -1551,16 +1504,66 @@ scsi_cdrom_command_chinon(void *sc, const uint8_t *cdb, UNUSED(int32_t *BufLen)) return cmd_stat; } +static void +scsi_cdrom_cache_toc(scsi_cdrom_t *dev) +{ + if (!dev->toc_cached) { + dev->toc_cached = 1; + dev->drv->seek_diff = dev->drv->seek_pos + 150; + dev->sector_pos = -150; + dev->drv->seek_pos = -150; + dev->requested_blocks = 150; + dev->drv->cached_sector = -1; + } +} + +static void +scsi_cdrom_one_sector_seek(scsi_cdrom_t *dev) +{ + if (!dev->was_cached) { + dev->drv->seek_diff = 0; + dev->requested_blocks = 1; + } +} + +static void +scsi_cdrom_media_access_complete(scsi_cdrom_t *dev, const int ret) +{ + ui_sb_update_icon(SB_CDROM | dev->id, 0); + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); +} + +static void +scsi_cdrom_read(scsi_common_t *sc) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; + const int ret = scsi_cdrom_read_blocks(dev); + + dev->drv->seek_diff = 0; + + if (ret > 0) { + if (dev->packet_status != PHASE_COMPLETE) { + ui_sb_update_icon(SB_CDROM | dev->id, 1); + + scsi_cdrom_set_period(dev); + } else + ui_sb_update_icon(SB_CDROM | dev->id, 0); + } else + scsi_cdrom_media_access_complete(dev, ret); +} + static uint8_t scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; - int msf; + int ret = 1; uint8_t cmd_stat = 0x00; + int msf; int len; int max_len; - int alloc_length; - int real_pos; switch (cdb[0]) { default: @@ -1575,7 +1578,9 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_TOC_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - msf = dev->drv->sony_msf; + dev->was_cached = dev->toc_cached; + + msf = dev->drv->sony_msf; max_len = cdb[7]; max_len <<= 8; @@ -1592,6 +1597,8 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) /* If the returned length is -1, this means cdrom_read_toc_sony() has encountered an error. */ scsi_cdrom_invalid_field(dev, dev->drv->inv_field); else { + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } @@ -1601,6 +1608,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_SUBCHANNEL_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector != -1); max_len = cdb[7]; max_len <<= 8; @@ -1615,6 +1623,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, 9); len = 9; cdrom_get_current_subchannel_sony(dev->drv, dev->buffer, msf); + scsi_cdrom_one_sector_seek(dev); len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -1631,23 +1640,54 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_HEADER_SONY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = ((cdb[7] << 8) | cdb[8]); - scsi_cdrom_buf_alloc(dev, 4); + len = (cdb[7] << 8) | cdb[8]; + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + dev->was_cached = (dev->drv->cached_sector == dev->sector_pos); + scsi_cdrom_log(dev->log, "READ HEADER SONY: Length: %i, LBA: %i\n", + dev->sector_len, dev->sector_pos); - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - dev->buffer[0] = ((real_pos >> 16) & 0xff); - dev->buffer[1] = ((real_pos >> 8) & 0xff); - dev->buffer[2] = real_pos & 0xff; - dev->buffer[3] = 1; /*2048 bytes user data*/ + if (len > 0) { + max_len = 1; + dev->requested_blocks = 1; - len = 4; - len = MIN(len, alloc_length); + dev->packet_len = len; + scsi_cdrom_buf_alloc(dev, 2352); - scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_one_sector_seek(dev); - scsi_cdrom_data_command_finish(dev, len, len, len, 0); + /* Any of these commands stop the audio playing. */ + cdrom_stop(dev->drv); + + dev->vendor_type = 0x00; + + dev->buffer_pos = 0x00000000; + + ret = scsi_cdrom_read_blocks(dev); + + if (ret > 0) { + len = MIN(4, len); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, + len, 0); + + ui_sb_update_icon(SB_CDROM | dev->id, 0); + } else { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = (ret < 0) ? PHASE_ERROR : PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + } + } else { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + /* scsi_cdrom_log(dev->log, "All done - callback set\n"); */ + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + } cmd_stat = 0x01; break; @@ -1702,7 +1742,11 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) scsi_cdrom_illegal_mode(dev); else { /* In this case, len is unused so just pass a fixed value of 1 intead. */ - const int ret = cdrom_audio_play(dev->drv, pos, 1, msf); + const int ret = cdrom_audio_play(dev->drv, pos, 1, msf); + dev->requested_blocks = 0; + + dev->drv->seek_diff = ABS(dev->sector_pos - dev->drv->seek_pos); + dev->sector_pos = dev->drv->seek_pos; if (ret) scsi_cdrom_command_complete(dev); @@ -1746,6 +1790,7 @@ scsi_cdrom_command_dec_sony_texel(void *sc, const uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 1); } + cmd_stat = 0x01; break; } @@ -1874,12 +1919,16 @@ scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->was_cached = 0; + if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DVD)) scsi_cdrom_illegal_mode(dev); else { - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); - dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); + + dev->drv->seek_diff = ABS(dev->sector_pos - dev->drv->seek_pos); + dev->sector_pos = dev->drv->seek_pos; if (ret) scsi_cdrom_command_complete(dev); @@ -1909,7 +1958,6 @@ scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_STILL_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); cdrom_audio_pause_resume(dev->drv, 0x00); - dev->drv->audio_op = 0x01; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; @@ -1924,12 +1972,14 @@ scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_stop(sc); cdrom_eject(dev->id); + dev->toc_cached = 0; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; case GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector == -1); alloc_length = cdb[1] & 0x1f; len = 10; @@ -1958,6 +2008,8 @@ scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_DISC_INFORMATION_NEC: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; + /* NEC manual claims 4 bytes but the Linux kernel (namely sr_vendor.c) actually states otherwise. @@ -1967,6 +2019,8 @@ scsi_cdrom_command_nec(void *sc, const uint8_t *cdb, int32_t *BufLen) ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); len = 22; if (ret) { + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else @@ -1998,12 +2052,15 @@ scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_stop(sc); cdrom_eject(dev->id); + dev->toc_cached = 0; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; case GPCMD_READ_TOC_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; + scsi_cdrom_buf_alloc(dev, 4); if (dev->drv->ops == NULL) @@ -2013,6 +2070,8 @@ scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) len = 4; if (ret) { + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else @@ -2023,6 +2082,7 @@ scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_SUBCODEQ_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector != -1); alloc_length = cdb[1] & 0x1f; len = 9; @@ -2041,6 +2101,7 @@ scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, len); cdrom_get_current_subcodeq(dev->drv, &dev->buffer[1]); + scsi_cdrom_one_sector_seek(dev); scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[0]); scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); @@ -2051,15 +2112,18 @@ scsi_cdrom_command_pioneer(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_PIONEER: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->was_cached = 0; + if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DVD)) ret = 0; else { pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; ret = cdrom_audio_track_search_pioneer(dev->drv, pos, cdb[1] & 1); - - dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; } + dev->drv->seek_diff = ABS(dev->sector_pos - dev->drv->seek_pos); + dev->sector_pos = dev->drv->seek_pos; + if (ret) scsi_cdrom_command_complete(dev); else @@ -2178,13 +2242,17 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->was_cached = 0; + if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DVD)) { scsi_cdrom_illegal_mode(dev); break; } - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); - dev->drv->audio_op = (cdb[1] & 1) ? 0x03 : 0x02; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search(dev->drv, pos, cdb[9] & 0xc0, cdb[1] & 1); + + dev->drv->seek_diff = ABS(dev->sector_pos - dev->drv->seek_pos); + dev->sector_pos = dev->drv->seek_pos; if (ret) scsi_cdrom_command_complete(dev); @@ -2213,7 +2281,6 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_STILL_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); cdrom_audio_pause_resume(dev->drv, 0x00); - dev->drv->audio_op = 0x01; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; @@ -2228,12 +2295,14 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_stop(sc); cdrom_eject(dev->id); + dev->toc_cached = 0; scsi_cdrom_command_complete(dev); cmd_stat = 0x01; break; case GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector != -1); alloc_length = cdb[1] & 0x1f; len = 10; @@ -2252,6 +2321,7 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) memset(dev->buffer, 0, len); dev->buffer[0] = cdrom_get_current_subcodeq_playstatus(dev->drv, &dev->buffer[1]); + scsi_cdrom_one_sector_seek(dev); scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[0]); scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); @@ -2262,6 +2332,8 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) case GPCMD_READ_DISC_INFORMATION_TOSHIBA: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; + scsi_cdrom_buf_alloc(dev, 4); if (dev->drv->ops == NULL) @@ -2270,6 +2342,8 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); len = 4; if (ret) { + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } else @@ -2277,6 +2351,25 @@ scsi_cdrom_command_toshiba(void *sc, const uint8_t *cdb, int32_t *BufLen) } cmd_stat = 0x01; break; + + case GPCMD_READ_CDROM_MODE_TOSHIBA: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector != -1); + + scsi_cdrom_buf_alloc(dev, 1); + + alloc_length = 1; + + len = alloc_length; + dev->buffer[0] = cdrom_get_current_mode(dev->drv); + + scsi_cdrom_one_sector_seek(dev); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + + cmd_stat = 0x01; + break; } return cmd_stat; @@ -2306,6 +2399,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) int toc_format; int32_t *BufLen; + dev->was_cached = -1; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; dev->tf->status &= ~ERR_STAT; @@ -2317,6 +2412,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->packet_len = 0; dev->request_pos = 0; + dev->block_len = 0; + memcpy(dev->current_cdb, cdb, 12); #if ENABLE_SCSI_CDROM_LOG == 2 @@ -2331,8 +2428,9 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) cdb[8], cdb[9], cdb[10], cdb[11]); #endif - msf = cdb[1] & 2; - dev->sector_len = 0; + msf = cdb[1] & 2; + dev->sector_len = 0; + dev->requested_blocks = 0; scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2348,17 +2446,22 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_sense_clear(dev, cdb[0]); } - if ((dev->ven_cmd == NULL) || (dev->ven_cmd(sc, cdb, BufLen) == 0x00)) switch (dev->current_cdb[0]) { + if ((dev->ven_cmd == NULL) || + (dev->ven_cmd(sc, cdb, BufLen) == 0x00)) switch (dev->current_cdb[0]) { case GPCMD_TEST_UNIT_READY: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); scsi_cdrom_command_complete(dev); break; case GPCMD_REZERO_UNIT: + pclog("Rezero unit\n"); + dev->was_cached = 0; scsi_cdrom_stop(sc); - dev->sector_pos = dev->sector_len = 0; + dev->requested_blocks = 0; dev->drv->seek_diff = dev->drv->seek_pos; cdrom_seek(dev->drv, 0, 0); + dev->sector_pos = dev->drv->seek_pos; + dev->drv->cached_sector = -1; scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); break; @@ -2386,7 +2489,9 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_SCAN_PIONEER: case GPCMD_AUDIO_SCAN: + pclog("Audio scan\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->was_cached = 0; if ((dev->drv->image_path[0] == 0x00) || (dev->drv->cd_status <= CD_STATUS_DVD)) { @@ -2395,7 +2500,10 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) } pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - ret = cdrom_audio_scan(dev->drv, pos, 0); + ret = cdrom_audio_scan(dev->drv, pos); + + dev->drv->seek_diff = ABS(dev->sector_pos - dev->drv->seek_pos); + dev->sector_pos = dev->drv->seek_pos; if (ret) scsi_cdrom_command_complete(dev); @@ -2419,6 +2527,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_TOC_PMA_ATIP: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; max_len = cdb[7]; max_len <<= 8; @@ -2427,6 +2536,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); toc_format = cdb[2] & 0xf; + pclog("READ TOC format %1X\n", toc_format); if (toc_format == 0) toc_format = (cdb[9] >> 6) & 3; @@ -2439,6 +2549,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) if (len == -1) scsi_cdrom_invalid_field(dev, dev->drv->inv_field); else { + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); } @@ -2446,6 +2558,16 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_invalid_field(dev, toc_format); break; + case GPCMD_PLAY_CD: + /* + According to the ATAPI specification, this was actually READ CD + on early drives. + */ + if (!dev->drv->is_early) { + scsi_cdrom_illegal_opcode(dev, dev->current_cdb[0]); + break; + } + fallthrough; case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: @@ -2454,9 +2576,11 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_CD: case GPCMD_READ_CD_MSF: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = dev->drv->sector_size; + dev->was_cached = 0; - switch (cdb[0]) { + alloc_length = dev->drv->sector_size; + + switch (dev->current_cdb[0]) { case GPCMD_READ_6: dev->sector_len = cdb[4]; /* @@ -2491,6 +2615,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_CD_MSF: msf = 1; fallthrough; + case GPCMD_PLAY_CD: case GPCMD_READ_CD_OLD: case GPCMD_READ_CD: alloc_length = 2856; @@ -2535,22 +2660,30 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); dev->drv->seek_pos = dev->sector_pos; - if (dev->use_cdb_9 && ((cdb[0] == GPCMD_READ_10) || - (cdb[0] == GPCMD_READ_12))) - ret = scsi_cdrom_read_blocks(dev, &alloc_length, - cdb[9] & 0xc0); + /* Any of these commands stop the audio playing. */ + cdrom_stop(dev->drv); + + if (dev->use_cdb_9 && + ((dev->current_cdb[0] == GPCMD_READ_10) || + (dev->current_cdb[0] == GPCMD_READ_12))) + dev->vendor_type = cdb[9] & 0xc0; else - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 0); + dev->vendor_type = 0x00; + + dev->block_len = 0xffffffff; + dev->buffer_pos = 0x00000000; + + ret = scsi_cdrom_read_blocks(dev); + alloc_length = dev->requested_blocks * dev->block_len; if (ret > 0) { - dev->requested_blocks = max_len; dev->packet_len = alloc_length; scsi_cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); scsi_cdrom_data_command_finish(dev, alloc_length, - alloc_length / dev->requested_blocks, + dev->block_len, alloc_length, 0); if (dev->packet_status != PHASE_COMPLETE) @@ -2575,11 +2708,14 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_HEADER: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = 2352; - len = (cdb[7] << 8) | cdb[8]; - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + alloc_length = 2352; + + len = (cdb[7] << 8) | cdb[8]; + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | + (cdb[4] << 8) | cdb[5]; + dev->was_cached = (dev->drv->cached_sector == dev->sector_pos); scsi_cdrom_log(dev->log, "READ HEADER: Length: %i, LBA: %i\n", dev->sector_len, dev->sector_pos); @@ -2590,10 +2726,15 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->packet_len = len; scsi_cdrom_buf_alloc(dev, 2352); - dev->drv->seek_diff = ABS((int) (pos - dev->sector_pos)); - dev->drv->seek_pos = dev->sector_pos; + scsi_cdrom_one_sector_seek(dev); - ret = scsi_cdrom_read_blocks(dev, &alloc_length, 0); + /* Any of these commands stop the audio playing. */ + cdrom_stop(dev->drv); + + dev->vendor_type = 0x00; + + dev->buffer_pos = 0x00000000; + ret = scsi_cdrom_read_blocks(dev); if (ret > 0) { uint8_t header[4] = { 0 }; @@ -2650,7 +2791,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) else block_desc = !((cdb[1] >> 3) & 1); - if (cdb[0] == GPCMD_MODE_SENSE_6) { + if (dev->current_cdb[0] == GPCMD_MODE_SENSE_6) { len = cdb[4]; scsi_cdrom_buf_alloc(dev, 256); } else { @@ -2681,7 +2822,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) else max_len = 3; /* Audio or mixed-mode CD. */ - if (cdb[0] == GPCMD_MODE_SENSE_6) { + if (dev->current_cdb[0] == GPCMD_MODE_SENSE_6) { len = scsi_cdrom_mode_sense(dev, dev->buffer, 4, cdb[2], block_desc); len = MIN(len, alloc_length); dev->buffer[0] = len - 1; @@ -2714,7 +2855,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_MODE_SELECT_10: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); - if (cdb[0] == GPCMD_MODE_SELECT_6) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { len = cdb[4]; scsi_cdrom_buf_alloc(dev, 256); } else { @@ -2919,7 +3060,10 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) gesn_event_header->notification_class |= GESN_MEDIA; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status. */ - dev->buffer[4] = dev->media_status; + if (dev->drv->cd_status == CD_STATUS_EMPTY) + dev->buffer[4] = MEC_MEDIA_REMOVAL; + else + dev->buffer[4] = dev->unit_attention ? MEC_NEW_MEDIA : MEC_NO_CHANGE; /* Power Status (1 = Active). */ dev->buffer[5] = 1; dev->buffer[6] = 0; @@ -2947,6 +3091,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_DISC_INFORMATION: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; max_len = cdb[7]; max_len <<= 8; @@ -2958,6 +3103,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = MIN(34, max_len); + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -2965,6 +3112,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_TRACK_INFORMATION: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; max_len = cdb[7]; max_len <<= 8; @@ -2983,6 +3131,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->buffer[1] = (max_len - 2) & 0xff; } + scsi_cdrom_cache_toc(dev); + scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); } else @@ -2999,21 +3149,25 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = 0; - switch (cdb[0]) { + switch (dev->current_cdb[0]) { case GPCMD_PLAY_AUDIO_10: msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; + pclog("Play audio (10)\n"); break; case GPCMD_PLAY_AUDIO_12: msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + pclog("Play audio (12)\n"); break; case GPCMD_PLAY_AUDIO_MSF: msf = 1; pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + pclog("Play audio MSF: %2i:%02i.%02i-%2i:%02i.%02i\n", + cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8]); break; case GPCMD_PLAY_AUDIO_TRACK_INDEX: msf = 2; @@ -3022,16 +3176,19 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = cdb[7]; } else ret = 0; + pclog("Play audio track index\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: msf = 0x100 | cdb[6]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; + pclog("Play audio track relative (10)\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: msf = 0x100 | cdb[10]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + pclog("Play audio track relative (12)\n"); break; default: @@ -3039,9 +3196,11 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) } if (ret && (dev->drv->image_path[0] != 0x00) && - (dev->drv->cd_status > CD_STATUS_DVD)) - ret = cdrom_audio_play(dev->drv, pos, len, msf); - else + (dev->drv->cd_status > CD_STATUS_DVD)) { + ret = cdrom_audio_play(dev->drv, pos, len, msf); + + dev->sector_pos = dev->drv->seek_pos; + } else ret = 0; if (ret) @@ -3052,13 +3211,14 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_READ_SUBCHANNEL: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = (dev->drv->cached_sector != -1); max_len = cdb[7]; max_len <<= 8; max_len |= cdb[8]; msf = (cdb[1] >> 1) & 1; - scsi_cdrom_buf_alloc(dev, 32); + scsi_cdrom_buf_alloc(dev, 128); scsi_cdrom_log(dev->log, "Getting page %i (%s)\n", cdb[3], msf ? "MSF" : "LBA"); @@ -3090,23 +3250,23 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = alloc_length; - memset(dev->buffer, 0, 24); - pos = 0x00; - dev->buffer[pos++] = 0x00; - dev->buffer[pos++] = 0x00; /* Audio status */ - dev->buffer[pos++] = 0x00; - dev->buffer[pos++] = 0x00; /* Subchannel length */ - dev->buffer[pos++] = cdb[3]; /* Format code */ + memset(dev->buffer, 0x00, 128); - if (alloc_length != 4) { + if (alloc_length > 4) { + dev->buffer[4] = cdb[3]; /* Format code */ cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf); - dev->buffer[2] = alloc_length - 4; + alloc_length = MIN(max_len, alloc_length); + + dev->buffer[3] = (alloc_length - 4) & 0xff; + dev->buffer[4] = cdb[3]; /* Format code */ } dev->buffer[1] = cdrom_get_current_status(dev->drv); - scsi_cdrom_log(dev->log, "Audio Status = %02x\n", dev->buffer[1]); + scsi_cdrom_log(dev->log, "Audio status: %02X\n", dev->buffer[1]); + + scsi_cdrom_one_sector_seek(dev); len = MIN(len, max_len); scsi_cdrom_set_buf_len(dev, BufLen, &len); @@ -3119,7 +3279,6 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - scsi_cdrom_buf_alloc(dev, alloc_length); if ((cdb[7] < 0xc0) && (dev->drv->cd_status != CD_STATUS_DVD)) @@ -3168,10 +3327,13 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) This makes no sense under emulation as this would do absolutely nothing, so just break. */ + dev->toc_cached = 0; + scsi_cdrom_cache_toc(dev); break; case 2: /* Eject the disc if possible. */ scsi_cdrom_stop(sc); cdrom_eject(dev->id); + dev->toc_cached = 0; break; case 3: /* Load the disc (close tray). */ cdrom_reload(dev->id); @@ -3267,7 +3429,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) if (dev->drv->bus_type == CDROM_BUS_SCSI) { dev->buffer[3] = cdrom_get_scsi_std(dev->drv->type); - if (!strcmp(cdrom_get_vendor(dev->drv->type), "TOSHIBA")) + if (dev->drv->is_toshiba) /* Linked Command and Relative Addressing supported */ dev->buffer[7] = 0x88; } else { @@ -3287,7 +3449,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) ide_padstr8(dev->buffer + 32, 4, cdrom_get_revision(dev->drv->type)); /* Revision */ - if (cdrom_has_date(dev->drv->type)) { + if (dev->drv->is_pioneer) { dev->buffer[36] = 0x20; ide_padstr8(dev->buffer + 37, 10, "1991/01/01"); /* Date */ } @@ -3321,15 +3483,16 @@ atapi_out: case GPCMD_PAUSE_RESUME: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); cdrom_audio_pause_resume(dev->drv, cdb[8] & 0x01); - dev->drv->audio_op = (cdb[8] & 0x01) ? 0x03 : 0x01; scsi_cdrom_command_complete(dev); break; case GPCMD_SEEK_6: case GPCMD_SEEK_10: + pclog("Seek\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->was_cached = 0; - switch (cdb[0]) { + switch (dev->current_cdb[0]) { case GPCMD_SEEK_6: pos = (cdb[2] << 8) | cdb[3]; break; @@ -3346,16 +3509,20 @@ atapi_out: /* Stop the audio playing. */ cdrom_stop(dev->drv); - if (dev->use_cdb_9 && (cdb[0] == GPCMD_SEEK_10)) + if (dev->use_cdb_9 && (dev->current_cdb[0] == GPCMD_SEEK_10)) cdrom_seek(dev->drv, pos, cdb[9] & 0xc0); else cdrom_seek(dev->drv, pos, 0); + dev->sector_pos = dev->drv->seek_pos; + dev->drv->cached_sector = -1; + scsi_cdrom_command_complete(dev); break; case GPCMD_READ_CDROM_CAPACITY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + dev->was_cached = dev->toc_cached; scsi_cdrom_buf_alloc(dev, 8); @@ -3370,6 +3537,8 @@ atapi_out: scsi_cdrom_log(dev->log, "CD-ROM Capacity: %08X\n", dev->drv->cdrom_capacity - 1); + + scsi_cdrom_cache_toc(dev); scsi_cdrom_set_buf_len(dev, BufLen, &len); scsi_cdrom_data_command_finish(dev, len, len, len, 0); @@ -3388,7 +3557,7 @@ atapi_out: break; default: - scsi_cdrom_illegal_opcode(dev, cdb[0]); + scsi_cdrom_illegal_opcode(dev, dev->current_cdb[0]); break; } @@ -3486,7 +3655,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) pos += 2; - if (dev->is_sony && (page == 0x08) && (page_len == 0x02)) + if (dev->drv->is_sony && (page == 0x08) && (page_len == 0x02)) dev->drv->sony_msf = dev->buffer[pos] & 0x01; if (!(dev->ms_page_flags & (1LL << ((uint64_t) page)))) { @@ -3496,7 +3665,9 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) for (i = 0; i < page_len; i++) { uint8_t pg = page; - if (dev->is_sony && (page == GPMODE_CDROM_AUDIO_PAGE_SONY) && (i >= 6) && (i <= 13)) + if (dev->drv->is_sony && + (page == GPMODE_CDROM_AUDIO_PAGE_SONY) && + (i >= 6) && (i <= 13)) pg = GPMODE_CDROM_AUDIO_PAGE; ch = dev->ms_pages_changeable.pages[pg][i + 2]; @@ -3532,7 +3703,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) } break; case 0xc9: - if (dev->is_sony) { + if (dev->drv->is_sony) { for (i = 0; i < 18; i++) { if ((i >= 8) && (i <= 15)) dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][i] = @@ -3687,12 +3858,15 @@ scsi_cdrom_drive_reset(const int c) dev->id = c; dev->drv = drv; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->cur_lun = SCSI_LUN_USE_CDB; - drv->insert = scsi_cdrom_insert; - drv->get_volume = scsi_cdrom_get_volume; - drv->get_channel = scsi_cdrom_get_channel; - drv->close = scsi_cdrom_close; + dev->toc_cached = 0; + drv->cached_sector = -1; + + drv->insert = scsi_cdrom_insert; + drv->get_volume = scsi_cdrom_get_volume; + drv->get_channel = scsi_cdrom_get_channel; + drv->close = scsi_cdrom_close; drv->sector_size = 2048; (void) scsi_cdrom_update_sector_flags(dev); @@ -3702,22 +3876,19 @@ scsi_cdrom_drive_reset(const int c) dev->ven_cmd = NULL; memset(dev->ven_cmd_is_data, 0x00, sizeof(dev->ven_cmd_is_data)); - dev->is_sony = 0; dev->use_cdb_9 = 0; dev->ms_page_flags = scsi_cdrom_ms_page_flags_scsi; dev->ms_pages_default = scsi_cdrom_ms_pages_default_scsi; dev->ms_pages_changeable = scsi_cdrom_ms_pages_changeable_scsi; - if (!strcmp(vendor, "CHINON")) + if (dev->drv->is_chinon) dev->ven_cmd = scsi_cdrom_command_chinon; - else if (!strcmp(vendor, "DEC") || !strcmp(vendor, "ShinaKen") || - !strcmp(vendor, "SONY") || !strcmp(vendor, "TEXEL")) { + else if (dev->drv->is_sony) { dev->ven_cmd = scsi_cdrom_command_dec_sony_texel; dev->ven_cmd_is_data[0xc0] = 1; dev->ven_cmd_is_data[0xc1] = 1; dev->ven_cmd_is_data[0xc2] = 1; dev->ven_cmd_is_data[0xc3] = 1; - dev->is_sony = 1; dev->ms_page_flags = scsi_cdrom_ms_page_flags_sony_scsi; dev->ms_pages_default = scsi_cdrom_ms_pages_default_sony_scsi; dev->ms_pages_changeable = scsi_cdrom_ms_pages_changeable_sony_scsi; @@ -3727,12 +3898,12 @@ scsi_cdrom_drive_reset(const int c) dev->ven_cmd = scsi_cdrom_command_nec; dev->ven_cmd_is_data[0xdd] = 1; dev->ven_cmd_is_data[0xde] = 1; - } else if (!strcmp(vendor, "PIONEER")) { + } else if (dev->drv->is_pioneer) { dev->ven_cmd = scsi_cdrom_command_pioneer; dev->ven_cmd_is_data[0xc1] = 1; dev->ven_cmd_is_data[0xc2] = 1; dev->ven_cmd_is_data[0xc3] = 1; - } else if (!strcmp(vendor, "TOSHIBA")) { + } else if (dev->drv->is_toshiba) { dev->ven_cmd = scsi_cdrom_command_toshiba; dev->ven_cmd_is_data[0xc6] = 1; dev->ven_cmd_is_data[0xc7] = 1; @@ -3768,7 +3939,6 @@ scsi_cdrom_drive_reset(const int c) if (id) { dev->ven_cmd = NULL; memset(dev->ven_cmd_is_data, 0x00, sizeof(dev->ven_cmd_is_data)); - dev->is_sony = 0; dev->use_cdb_9 = 0; dev->ms_page_flags = scsi_cdrom_ms_page_flags; dev->ms_pages_default = scsi_cdrom_ms_pages_default; @@ -3786,6 +3956,8 @@ scsi_cdrom_drive_reset(const int c) id->phase_data_out = scsi_cdrom_phase_data_out; id->command_stop = scsi_cdrom_command_stop; id->bus_master_error = scsi_cdrom_bus_master_error; + id->read = scsi_cdrom_read; + id->write = NULL; id->interrupt_drq = dev->drv->is_early; valid = 1; diff --git a/src/sound/sound.c b/src/sound/sound.c index 28cb96629..0c8dffe12 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -274,83 +274,89 @@ sound_cd_thread(UNUSED(void *param)) temp_buffer[0] = temp_buffer[1] = 0; for (uint8_t i = 0; i < CDROM_NUM; i++) { - if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY)) + /* Just in case the thread is in a loop when it gets terminated. */ + if (!cdaudioon) + break; + + if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || + (cdrom[i].cd_status != CD_STATUS_PLAYING)) continue; - const uint32_t lba = cdrom[i].seek_pos; - const int r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2); - if (!cdrom[i].sound_on || !r) - continue; - const int pre = cdrom_is_pre(&(cdrom[i]), lba); + const int ret = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], + CD_BUFLEN * 2); - - if (cdrom[i].get_volume) { - audio_vol_l = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 0)]; - audio_vol_r = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 1)]; - } else { - audio_vol_l = cd_audio_volume_lut[255]; - audio_vol_r = cd_audio_volume_lut[255]; - } - - if (cdrom[i].get_channel) { - channel_select[0] = (int) cdrom[i].get_channel(cdrom[i].priv, 0); - channel_select[1] = (int) cdrom[i].get_channel(cdrom[i].priv, 1); - } else { - channel_select[0] = 1; - channel_select[1] = 2; - } - - for (int c = 0; c < CD_BUFLEN * 2; c += 2) { - /*Apply ATAPI channel select*/ - cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0; - - if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) { - if (channel_select[0] & 1) - cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */ - if (channel_select[0] & 2) - cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */ - - cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */ - - if (pre) - cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */ - } - - if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { - if (channel_select[1] & 1) - cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */ - if (channel_select[1] & 2) - cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */ - - cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */ - - if (pre) - cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */ - } - - /* Apply sound card CD volume and filters */ - if (filter_cd_audio != NULL) { - filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p); - filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p); - } - - if (sound_is_float) { - cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0); - cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0); + if (ret) { + if (cdrom[i].get_volume) { + audio_vol_l = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 0)]; + audio_vol_r = cd_audio_volume_lut[cdrom[i].get_volume(cdrom[i].priv, 1)]; } else { - temp_buffer[0] += (int) trunc(cd_buffer_temp[0]); - temp_buffer[1] += (int) trunc(cd_buffer_temp[1]); + audio_vol_l = cd_audio_volume_lut[255]; + audio_vol_r = cd_audio_volume_lut[255]; + } - if (temp_buffer[0] > 32767) - temp_buffer[0] = 32767; - if (temp_buffer[0] < -32768) - temp_buffer[0] = -32768; - if (temp_buffer[1] > 32767) - temp_buffer[1] = 32767; - if (temp_buffer[1] < -32768) - temp_buffer[1] = -32768; + if (cdrom[i].get_channel) { + channel_select[0] = (int) cdrom[i].get_channel(cdrom[i].priv, 0); + channel_select[1] = (int) cdrom[i].get_channel(cdrom[i].priv, 1); + } else { + channel_select[0] = 1; + channel_select[1] = 2; + } - cd_out_buffer_int16[c] = (int16_t) temp_buffer[0]; - cd_out_buffer_int16[c + 1] = (int16_t) temp_buffer[1]; + // uint16_t *cddab = (uint16_t *) cdrom[i].raw_buffer; + for (int c = 0; c < CD_BUFLEN * 2; c += 2) { + /* Apply ATAPI channel select */ + cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0; + + if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) { + if (channel_select[0] & 1) + /* Channel 0 => Port 0 */ + cd_buffer_temp[0] += ((double) cd_buffer[i][c]); + if (channel_select[0] & 2) + /* Channel 1 => Port 0 */ + cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); + + /* Multiply Port 0 by Port 0 volume */ + cd_buffer_temp[0] *= audio_vol_l; + } + + if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) { + if (channel_select[1] & 1) + /* Channel 0 => Port 1 */ + cd_buffer_temp[1] += ((double) cd_buffer[i][c]); + if (channel_select[1] & 2) + /* Channel 1 => Port 1 */ + cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); + + /* Multiply Port 1 by Port 1 volume */ + cd_buffer_temp[1] *= audio_vol_r; + } + + /* Apply sound card CD volume and filters */ + if (filter_cd_audio != NULL) { + filter_cd_audio(0, &(cd_buffer_temp[0]), + filter_cd_audio_p); + filter_cd_audio(1, &(cd_buffer_temp[1]), + filter_cd_audio_p); + } + + if (sound_is_float) { + cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0); + cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0); + } else { + temp_buffer[0] = (int) trunc(cd_buffer_temp[0]); + temp_buffer[1] = (int) trunc(cd_buffer_temp[1]); + + if (temp_buffer[0] > 32767) + temp_buffer[0] = 32767; + if (temp_buffer[0] < -32768) + temp_buffer[0] = -32768; + if (temp_buffer[1] > 32767) + temp_buffer[1] = 32767; + if (temp_buffer[1] < -32768) + temp_buffer[1] = -32768; + + cd_out_buffer_int16[c] += (int16_t) temp_buffer[0]; + cd_out_buffer_int16[c + 1] += (int16_t) temp_buffer[1]; + } } } } From ae597c2e46c3097d5f13631d408c4761022e0f90 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 10 Feb 2025 05:31:29 +0100 Subject: [PATCH 002/158] Reverted the dark mode forcing and reveted CD-ROM to old behavior if bus is SCSI, because it turns out the changes are not even needed on SCSI. --- src/qt/qt_winrawinputfilter.cpp | 1 - src/scsi/scsi_cdrom.c | 15 +++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 272b389c5..13e0ec9a7 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -65,7 +65,6 @@ extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); #include "ui_qt_mainwindow.h" bool windows_is_light_theme() { - return 0; // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application // The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 07590d5ae..8a39edb39 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -611,7 +611,9 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, const int block_len break; } } - dev->requested_blocks = 1; + + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->requested_blocks = 1; fallthrough; default: @@ -1044,11 +1046,12 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int if (dev->drv->cd_status == CD_STATUS_EMPTY) scsi_cdrom_not_ready(dev); - else { - if (dev->sector_pos > dev->drv->cdrom_capacity) { - scsi_cdrom_lba_out_of_range(dev); - ret = -1; - } else { + else if (dev->sector_pos > dev->drv->cdrom_capacity) { + scsi_cdrom_lba_out_of_range(dev); + ret = -1; + } else { + ret = 1; + for (int i = 0; (i < dev->requested_blocks) && (ret > 0); i++) { ret = cdrom_readsector_raw(dev->drv, dev->buffer + dev->buffer_pos, dev->sector_pos, msf, type, flags, &temp_len, vendor_type); From 9a1ae5997fe3d63941aed2ecbb9cc771fc95604c Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 01:44:10 +0100 Subject: [PATCH 003/158] Fixed ATAPI transfer split by sectors and improved the performance of IOCTL by making it no longer constantly open and close the handle. --- src/cdrom/cdrom.c | 6 ++---- src/disk/hdc_ide.c | 1 - src/qt/win_cdrom_ioctl.c | 17 ----------------- src/scsi/scsi_cdrom.c | 16 ++++++++++------ 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 9f3b6e079..aab6cf67c 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2822,9 +2822,7 @@ cdrom_update_status(cdrom_t *dev) dev->seek_pos = 0; dev->cd_buflen = 0; - if ((dev->ops->is_empty != NULL) && dev->ops->is_empty(dev->local)) - dev->cd_status = CD_STATUS_EMPTY; - else if (dev->ops->is_dvd(dev->local)) + if (dev->ops->is_dvd(dev->local)) dev->cd_status = CD_STATUS_DVD; else dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED : @@ -3048,7 +3046,7 @@ cdrom_is_empty(const uint8_t id) int ret = 0; /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ - if (strlen(dev->image_path) == 0) + if ((strlen(dev->image_path) == 0) || (dev->cd_status == CD_STATUS_EMPTY)) /* Switch from empty to empty. Do nothing. */ ret = 1; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index e367f73b0..d42a595df 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -241,7 +241,6 @@ int ide_qua_enabled = 0; static void ide_atapi_callback(ide_t *ide); static void ide_callback(void *priv); -#define ENABLE_IDE_LOG 1 #ifdef ENABLE_IDE_LOG int ide_do_log = ENABLE_IDE_LOG; diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 3d9ecefd5..8da62a49d 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -124,12 +124,10 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) ioctl->cur_read_toc_ex.Msf = 1; ioctl->cur_read_toc_ex.SessionTrack = 1; - ioctl_open_handle(ioctl); const int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535, cur_full_toc, 65535, (LPDWORD) &size, NULL); - ioctl_close_handle(ioctl); ioctl_log(ioctl->log, "temp = %i\n", temp); if (temp != 0) { @@ -178,12 +176,10 @@ ioctl_read_raw_toc(ioctl_t *ioctl) ioctl->cur_read_toc_ex.Msf = 1; ioctl->cur_read_toc_ex.SessionTrack = 1; - ioctl_open_handle(ioctl); const int status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, &ioctl->cur_read_toc_ex, 65535, cur_full_toc, 65535, (LPDWORD) &size, NULL); - ioctl_close_handle(ioctl); ioctl_log(ioctl->log, "status = %i\n", status); if ((status == 0) && (ioctl->tracks_num >= 1)) { @@ -384,8 +380,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) int ret; SCSI_PASS_THROUGH_DIRECT_BUF req; - ioctl_open_handle((ioctl_t *) ioctl); - if (ioctl->is_dvd) { int track; @@ -517,8 +511,6 @@ ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector) for (int j = 7; j >= 0; j--) buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6; - ioctl_close_handle((ioctl_t *) ioctl); - return ret; } @@ -587,8 +579,6 @@ ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t f const int len = 2052; SCSI_PASS_THROUGH_DIRECT_BUF req; - ioctl_open_handle((ioctl_t *) ioctl); - memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF)); req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); req.spt.PathId = 0; @@ -650,8 +640,6 @@ ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t f } else ret = ret ? (req.spt.DataTransferLength >= len) : 0; - ioctl_close_handle((ioctl_t *) ioctl); - return ret; } @@ -684,8 +672,6 @@ ioctl_is_empty(const void *local) unsigned long int unused = 0; SCSI_PASS_THROUGH_DIRECT_BUF req; - ioctl_open_handle((ioctl_t *) ioctl); - memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF)); req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); req.spt.PathId = 0; @@ -745,8 +731,6 @@ ioctl_is_empty(const void *local) } else ret = 0; - ioctl_close_handle((ioctl_t *) ioctl); - return ret; } @@ -774,7 +758,6 @@ ioctl_load(const void *local) DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, (LPDWORD) &size, NULL); - ioctl_close_handle((ioctl_t *) ioctl); ioctl_read_toc((ioctl_t *) ioctl); } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 8a39edb39..53a079d6a 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -15,7 +15,6 @@ */ #include #include -#define ENABLE_SCSI_CDROM_LOG 2 #ifdef ENABLE_SCSI_CDROM_LOG #include #endif @@ -704,8 +703,11 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) if (dev->was_cached == -1) period *= (double) dev->packet_len; else { - period *= ((double) dev->requested_blocks) * 2352.0; - pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, dev->requested_blocks); + const int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? + dev->requested_blocks : 1; + + period *= ((double) num) * 2352.0; + pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, num); } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); @@ -1041,8 +1043,10 @@ static int scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int flags, const int vendor_type) { - int temp_len = 0; - int ret = 0; + int temp_len = 0; + int ret = 0; + const int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? + dev->requested_blocks : 1; if (dev->drv->cd_status == CD_STATUS_EMPTY) scsi_cdrom_not_ready(dev); @@ -1051,7 +1055,7 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int ret = -1; } else { ret = 1; - for (int i = 0; (i < dev->requested_blocks) && (ret > 0); i++) { + for (int i = 0; (i < num) && (ret > 0); i++) { ret = cdrom_readsector_raw(dev->drv, dev->buffer + dev->buffer_pos, dev->sector_pos, msf, type, flags, &temp_len, vendor_type); From 8a66dbef372b1f06f107f8514fc41105380f52cb Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 04:28:05 +0100 Subject: [PATCH 004/158] Fixed ATAPI PIO operation and ATAPI DMA timings. --- src/disk/hdc_ide.c | 116 ++++++++++++++++++++++++++++++++---------- src/scsi/scsi_cdrom.c | 62 ++++++++++++---------- 2 files changed, 125 insertions(+), 53 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index d42a595df..8559d7a63 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -241,6 +241,7 @@ int ide_qua_enabled = 0; static void ide_atapi_callback(ide_t *ide); static void ide_callback(void *priv); +// #define ENABLE_IDE_LOG 1 #ifdef ENABLE_IDE_LOG int ide_do_log = ENABLE_IDE_LOG; @@ -1091,6 +1092,7 @@ ide_atapi_callback(ide_t *ide) ide_irq_raise(ide); break; case PHASE_DATA_IN_DMA: + pclog("Reading block %i... ", ide->sc->sector_len + 1); if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { if (ide->sc->block_len == 0) @@ -1114,13 +1116,16 @@ ide_atapi_callback(ide_t *ide) default: break; case 0: + pclog("ERROR\n"); if (ide->bus_master_error) ide->bus_master_error(ide->sc); break; case 2: + pclog("WAIT\n"); ide_atapi_command_bus(ide); break; case 3: + pclog("DONE\n"); /* Reached EOT - terminate the command as there's nothing more to transfer. */ ide->sc->packet_status = PHASE_COMPLETE; @@ -1130,6 +1135,7 @@ ide_atapi_callback(ide_t *ide) ide->command_stop(ide->sc); fallthrough; case 1: + pclog("NEXT\n"); if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) ide_atapi_callback(ide); @@ -1193,21 +1199,15 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide_irq_lower(ide); - ide->tf->atastat = BSY_STAT; + ide->tf->atastat = BSY_STAT; if (ide->tf->pos >= dev->packet_len) { ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read"); ide->tf->pos = dev->request_pos = 0; - if (dev->block_len != 0) { - if (out && (ide->write != NULL)) - ide->write(dev); - else if (!out && (dev->sector_len != 0) && (ide->read != NULL)) - ide->read(dev); - } - - if ((dev->block_len == 0) || (dev->sector_len == 0)) { + if (dev->block_len == 0) { + // pclog("ide_atapi_pio_request(): Processing instant command...\n"); if (out && (ide->phase_data_out != NULL)) ide->phase_data_out(dev); else if (!out && (ide->command_stop != NULL)) @@ -1237,22 +1237,62 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) dev->packet_status = PHASE_DATA_IN | out; - if (dev->block_len != 0) { - if (out && (ide->write != NULL)) - ide->write(dev); - else if (!out && (dev->sector_len != 0) && (ide->read != NULL)) - ide->read(dev); - } - - ide->tf->atastat = BSY_STAT; - ide->tf->phase = 1; - - if ((dev->block_len == 0) || (dev->sector_len == 0)) { + if (dev->block_len == 0) { ide_atapi_callback(ide); ide_set_callback(ide, 0.0); } - dev->request_pos = 0; + dev->request_pos = 0; + } + + if (dev->block_len != 0) { + if (out) { + if (ide->write != NULL) { +#if 0 + pclog("ide_atapi_pio_request(): Continuing write command " + "(dev->sector_len = %i)...\n", dev->sector_len); +#endif + + ide->write(dev); + } + + if (dev->sector_len == 0) { +#if 0 + pclog("ide_atapi_pio_request(): Ending write command " + "(dev->sector_len = %i)...\n", dev->sector_len); +#endif + + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; + + if (ide->phase_data_out != NULL) + (void) ide->phase_data_out(dev); + + ide_atapi_callback(ide); + } + } else { + if (dev->sector_len == 0) { +#if 0 + pclog("ide_atapi_pio_request(): Ending read command " + "(dev->sector_len = %i)...\n", dev->sector_len); +#endif + + if (ide->command_stop != NULL) + ide->command_stop(dev); + + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; + + ide_atapi_callback(ide); + } else if (ide->read != NULL) { +#if 0 + pclog("ide_atapi_pio_request(): Continuing read command " + "(dev->sector_len = %i)...\n", dev->sector_len); +#endif + + ide->read(dev); + } + } } } @@ -1284,11 +1324,27 @@ ide_atapi_packet_read(ide_t *ide) (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ ide_atapi_pio_request(ide, 0); - } else if ((dev->block_len != 0) && + } +#if 0 + else if ((dev->block_len != 0) && (dev->sector_len != 0) && - ((dev->request_pos % dev->block_len) == 0) && - (ide->read != NULL)) - ide->read(dev); + ((dev->request_pos % dev->block_len) == 0)) { + if (dev->sector_len == 0) { + // pclog("ide_atapi_packet_read(): Ending read command (dev->sector_len = %i)...\n", dev->sector_len); + + if (ide->command_stop != NULL) + ide->command_stop(ide->sc); + + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; + + ide_atapi_callback(ide); + } else if (ide->read != NULL) { + // pclog("ide_atapi_packet_read(): Continuing read command (dev->sector_len = %i)...\n", dev->sector_len); + ide->read(dev); + } + } +#endif } return ret; @@ -1322,10 +1378,16 @@ ide_atapi_packet_write(ide_t *ide, const uint16_t val) (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ ide_atapi_pio_request(ide, 1); - } else if ((dev->block_len != 0) && + } +#if 0 + else if ((dev->block_len != 0) && ((dev->request_pos % dev->block_len) == 0) && - (ide->write != NULL)) + (ide->write != NULL)) { + // pclog("ide_atapi_packet_write(): Continuing write command (dev->sector_len = %i)...\n", dev->sector_len); + ide->write(dev); + } +#endif } else if (dev->packet_status == PHASE_IDLE) { if (ide->tf->pos >= 12) { ide->tf->pos = 0; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 53a079d6a..21ea9ce16 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -15,6 +15,7 @@ */ #include #include +// #define ENABLE_SCSI_CDROM_LOG 2 #ifdef ENABLE_SCSI_CDROM_LOG #include #endif @@ -611,8 +612,8 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, const int block_len } } - if (dev->drv->bus_type != CDROM_BUS_SCSI) - dev->requested_blocks = 1; + if ((dev->drv->bus_type != CDROM_BUS_SCSI) && (dev->block_len != 0)) + dev->requested_blocks = (dev->packet_len / dev->block_len); fallthrough; default: @@ -667,9 +668,9 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) scsi_cdrom_log(dev->log, "Current speed: %ix\n", dev->drv->cur_speed); - if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0; - else { + dev->callback = 0; + + if (dev->packet_status != PHASE_COMPLETE) { double bytes_per_second; double period; @@ -689,6 +690,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; + // pclog("Current speed: %ix\n", dev->drv->cur_speed); } else { bytes_per_second = scsi_cdrom_bus_speed(dev); if (bytes_per_second == 0.0) { @@ -703,8 +705,11 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) if (dev->was_cached == -1) period *= (double) dev->packet_len; else { - const int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? - dev->requested_blocks : 1; + const int num = ((dev->drv->bus_type == CDROM_BUS_SCSI) || + (dev->block_len == 0)) ? + dev->requested_blocks : + ((scsi_cdrom_current_mode(dev) == 2) ? 1 : + (dev->packet_len / dev->block_len)); period *= ((double) num) * 2352.0; pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, num); @@ -1045,7 +1050,7 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int { int temp_len = 0; int ret = 0; - const int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? + int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? dev->requested_blocks : 1; if (dev->drv->cd_status == CD_STATUS_EMPTY) @@ -1065,15 +1070,20 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int else if (ret == 0) scsi_cdrom_illegal_mode(dev); else { - if (dev->block_len == 0xffffffff) + if (dev->block_len == 0xffffffff) { dev->block_len = temp_len; + if ((dev->drv->bus_type != CDROM_BUS_SCSI) && + (scsi_cdrom_current_mode(dev) != 2)) + num = (dev->packet_len / dev->block_len); + } + dev->sector_pos++; dev->drv->seek_pos = dev->sector_pos; dev->sector_len--; - pclog("Sector read to buffer position %08X\n", dev->buffer_pos); + // pclog("Sector read to buffer position %08X\n", dev->buffer_pos); dev->buffer_pos += temp_len; } } @@ -1547,17 +1557,17 @@ static void scsi_cdrom_read(scsi_common_t *sc) { scsi_cdrom_t *dev = (scsi_cdrom_t *) sc; + const int osl = dev->sector_len; const int ret = scsi_cdrom_read_blocks(dev); dev->drv->seek_diff = 0; if (ret > 0) { - if (dev->packet_status != PHASE_COMPLETE) { - ui_sb_update_icon(SB_CDROM | dev->id, 1); - + if (osl > 0) scsi_cdrom_set_period(dev); - } else - ui_sb_update_icon(SB_CDROM | dev->id, 0); + + ui_sb_update_icon(SB_CDROM | dev->id, + (dev->packet_status != PHASE_COMPLETE)); } else scsi_cdrom_media_access_complete(dev, ret); } @@ -2461,7 +2471,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_REZERO_UNIT: - pclog("Rezero unit\n"); + // pclog("Rezero unit\n"); dev->was_cached = 0; scsi_cdrom_stop(sc); dev->requested_blocks = 0; @@ -2496,7 +2506,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_SCAN_PIONEER: case GPCMD_AUDIO_SCAN: - pclog("Audio scan\n"); + // pclog("Audio scan\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->was_cached = 0; @@ -2543,7 +2553,7 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); toc_format = cdb[2] & 0xf; - pclog("READ TOC format %1X\n", toc_format); + // pclog("READ TOC format %1X\n", toc_format); if (toc_format == 0) toc_format = (cdb[9] >> 6) & 3; @@ -3161,20 +3171,20 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; - pclog("Play audio (10)\n"); + // pclog("Play audio (10)\n"); break; case GPCMD_PLAY_AUDIO_12: msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - pclog("Play audio (12)\n"); + // pclog("Play audio (12)\n"); break; case GPCMD_PLAY_AUDIO_MSF: msf = 1; pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - pclog("Play audio MSF: %2i:%02i.%02i-%2i:%02i.%02i\n", - cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8]); + // pclog("Play audio MSF: %2i:%02i.%02i-%2i:%02i.%02i\n", + // cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8]); break; case GPCMD_PLAY_AUDIO_TRACK_INDEX: msf = 2; @@ -3183,19 +3193,19 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = cdb[7]; } else ret = 0; - pclog("Play audio track index\n"); + // pclog("Play audio track index\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: msf = 0x100 | cdb[6]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; - pclog("Play audio track relative (10)\n"); + // pclog("Play audio track relative (10)\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: msf = 0x100 | cdb[10]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - pclog("Play audio track relative (12)\n"); + // pclog("Play audio track relative (12)\n"); break; default: @@ -3495,7 +3505,7 @@ atapi_out: case GPCMD_SEEK_6: case GPCMD_SEEK_10: - pclog("Seek\n"); + // pclog("Seek\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->was_cached = 0; From 4221b7205997d1dab8c1f3513036a9f25443c009 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 04:28:52 +0100 Subject: [PATCH 005/158] Commented out some logging stuff. --- src/scsi/scsi_cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 21ea9ce16..8c24c4623 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -712,7 +712,7 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) (dev->packet_len / dev->block_len)); period *= ((double) num) * 2352.0; - pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, num); + // pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, num); } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); From 1a87aea37aa05742402825ee11618628431edfe5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 04:32:59 +0100 Subject: [PATCH 006/158] And some more. --- src/disk/hdc_ide.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 8559d7a63..d4dcea625 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1092,7 +1092,7 @@ ide_atapi_callback(ide_t *ide) ide_irq_raise(ide); break; case PHASE_DATA_IN_DMA: - pclog("Reading block %i... ", ide->sc->sector_len + 1); + // pclog("Reading block %i... ", ide->sc->sector_len + 1); if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { if (ide->sc->block_len == 0) @@ -1116,16 +1116,16 @@ ide_atapi_callback(ide_t *ide) default: break; case 0: - pclog("ERROR\n"); + // pclog("ERROR\n"); if (ide->bus_master_error) ide->bus_master_error(ide->sc); break; case 2: - pclog("WAIT\n"); + // pclog("WAIT\n"); ide_atapi_command_bus(ide); break; case 3: - pclog("DONE\n"); + // pclog("DONE\n"); /* Reached EOT - terminate the command as there's nothing more to transfer. */ ide->sc->packet_status = PHASE_COMPLETE; @@ -1135,7 +1135,7 @@ ide_atapi_callback(ide_t *ide) ide->command_stop(ide->sc); fallthrough; case 1: - pclog("NEXT\n"); + // pclog("NEXT\n"); if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) ide_atapi_callback(ide); From 5262693624f540eaba572ee05c63665998501bed Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 04:53:51 +0100 Subject: [PATCH 007/158] IOCTL: The host non-raw TOC is no longer always read and is also only used to reconstruct the raw toc for DVD's, should reduce the slowness on host drive mounting. --- src/qt/win_cdrom_ioctl.c | 104 +++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 8da62a49d..96b75db38 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -44,8 +44,6 @@ typedef struct ioctl_t { int is_dvd; int has_audio; int32_t tracks_num; - uint8_t cur_toc[65536]; - CDROM_READ_TOC_EX cur_read_toc_ex; int blocks_num; uint8_t cur_rti[65536]; HANDLE handle; @@ -111,22 +109,23 @@ ioctl_open_handle(ioctl_t *ioctl) static int ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) { - long size = 0; - PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; + long size = 0; + PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; + CDROM_READ_TOC_EX cur_read_toc_ex = { 0 }; ioctl->tracks_num = 0; memset(toc_buf, 0x00, 65536); cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536); - ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC; - ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format); - ioctl->cur_read_toc_ex.Msf = 1; - ioctl->cur_read_toc_ex.SessionTrack = 1; + cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_TOC; + ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", cur_read_toc_ex.Format); + cur_read_toc_ex.Msf = 1; + cur_read_toc_ex.SessionTrack = 1; const int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, - &ioctl->cur_read_toc_ex, 65535, - cur_full_toc, 65535, + &cur_read_toc_ex, 65535, + cur_full_toc, 65535, (LPDWORD) &size, NULL); ioctl_log(ioctl->log, "temp = %i\n", temp); @@ -157,10 +156,12 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) static void ioctl_read_raw_toc(ioctl_t *ioctl) { - PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; - long size = 0; - raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; - uint8_t *buffer = (uint8_t *) calloc (1, 2052); + PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; + long size = 0; + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; + uint8_t *buffer = (uint8_t *) calloc (1, 2052); + int status = 0; + CDROM_READ_TOC_EX cur_read_toc_ex = { 0 }; ioctl->is_dvd = (ioctl_read_dvd_structure(ioctl, 0, 0, buffer, NULL) > 0); free(buffer); @@ -171,16 +172,18 @@ ioctl_read_raw_toc(ioctl_t *ioctl) cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536); - ioctl->cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", ioctl->cur_read_toc_ex.Format); - ioctl->cur_read_toc_ex.Msf = 1; - ioctl->cur_read_toc_ex.SessionTrack = 1; + cur_read_toc_ex.Format = CDROM_READ_TOC_EX_FORMAT_FULL_TOC; + ioctl_log(ioctl->log, "cur_read_toc_ex.Format = %i\n", cur_read_toc_ex.Format); + cur_read_toc_ex.Msf = 1; + cur_read_toc_ex.SessionTrack = 1; - const int status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, - &ioctl->cur_read_toc_ex, 65535, - cur_full_toc, 65535, - (LPDWORD) &size, NULL); - ioctl_log(ioctl->log, "status = %i\n", status); + if (!ioctl->is_dvd) { + status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, + &cur_read_toc_ex, 65535, + cur_full_toc, 65535, + (LPDWORD) &size, NULL); + ioctl_log(ioctl->log, "status = %i\n", status); + } if ((status == 0) && (ioctl->tracks_num >= 1)) { /* @@ -189,8 +192,12 @@ ioctl_read_raw_toc(ioctl_t *ioctl) reading the cooked TOC does not, so we have to construct the raw TOC from the cooked TOC. */ - const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; - const TRACK_DATA *ct = &(toc->TrackData[ioctl->tracks_num - 1]); + uint8_t cur_toc[65536] = { 0 }; + + const CDROM_TOC * toc = (const CDROM_TOC *) cur_toc; + const TRACK_DATA *ct = &(toc->TrackData[ioctl->tracks_num - 1]); + + ioctl_read_normal_toc(ioctl, cur_toc); rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); rti[0].point = 0xa0; @@ -257,7 +264,6 @@ ioctl_read_raw_toc(ioctl_t *ioctl) static void ioctl_read_toc(ioctl_t *ioctl) { - (void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc); ioctl_read_raw_toc(ioctl); } @@ -306,23 +312,28 @@ static int ioctl_get_track_info(const void *local, const uint32_t track, int end, track_info_t *ti) { - const ioctl_t * ioctl = (const ioctl_t *) local; - const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; - int ret = 1; + const ioctl_t * ioctl = (const ioctl_t *) local; + const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti; + int ret = 1; + int trk = -1; - if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) { + if ((track >= 1) && (track < 99)) + for (int i = 0; i < ioctl->blocks_num; i++) + if (rti[i].point == track) { + trk = i; + break; + } + + if ((track == 0xaa) || (trk == -1)) { ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track); ret = 0; } else { - const TRACK_DATA * td = &toc->TrackData[track - 1]; + ti->m = rti[trk].pm; + ti->s = rti[trk].ps; + ti->f = rti[trk].pf; - ti->m = td->Address[1]; - ti->s = td->Address[2]; - ti->f = td->Address[3]; - - ti->number = td->TrackNumber; - ti->attr = td->Control; - ti->attr |= ((td->Adr << 4) & 0xf0); + ti->number = rti[trk].point; + ti->attr = rti[trk].adr_ctl; ioctl_log(ioctl->log, "ioctl_get_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n", track, ti->m, ti->s, ti->f, ti->number, ti->attr); @@ -546,18 +557,15 @@ ioctl_get_track_type(const void *local, const uint32_t sector) static uint32_t ioctl_get_last_block(const void *local) { - const ioctl_t *ioctl = (const ioctl_t *) local; - const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc; + const ioctl_t * ioctl = (const ioctl_t *) local; + raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; uint32_t lb = 0; - for (int c = 0; c <= toc->LastTrack; c++) { - const TRACK_DATA *td = &toc->TrackData[c]; - const uint32_t address = MSFtoLBA(td->Address[1], td->Address[2], - td->Address[3]) - 150; - - if (address > lb) - lb = address; - } + for (int i = (ioctl->blocks_num - 1); i >= 0; i--) + if (rti[i].point == 0xa2) { + lb = MSFtoLBA(rti[i].pm, rti[i].ps, rti[i].pf) - 151; + break; + } ioctl_log(ioctl->log, "LBCapacity=%d\n", lb); From 44c6daad1c3e8189222d4aa1a1a06a3656228acf Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 08:36:36 +0100 Subject: [PATCH 008/158] Fixed IOCTL failing to read raw TOC after hard reset. --- src/cdrom/cdrom.c | 2 +- src/qt/win_cdrom_ioctl.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index aab6cf67c..b34b01fff 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2873,7 +2873,7 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert) if ((dev->ops->is_empty != NULL) && dev->ops->is_empty(dev->local)) dev->cd_status = CD_STATUS_EMPTY; - if (dev->ops->is_dvd(dev->local)) + else if (dev->ops->is_dvd(dev->local)) dev->cd_status = CD_STATUS_DVD; else dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED : diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 96b75db38..40addd591 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -124,7 +124,7 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) cur_read_toc_ex.SessionTrack = 1; const int temp = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, - &cur_read_toc_ex, 65535, + &cur_read_toc_ex, sizeof(CDROM_READ_TOC_EX), cur_full_toc, 65535, (LPDWORD) &size, NULL); ioctl_log(ioctl->log, "temp = %i\n", temp); @@ -179,7 +179,7 @@ ioctl_read_raw_toc(ioctl_t *ioctl) if (!ioctl->is_dvd) { status = DeviceIoControl(ioctl->handle, IOCTL_CDROM_READ_TOC_EX, - &cur_read_toc_ex, 65535, + &cur_read_toc_ex, sizeof(CDROM_READ_TOC_EX), cur_full_toc, 65535, (LPDWORD) &size, NULL); ioctl_log(ioctl->log, "status = %i\n", status); @@ -261,12 +261,6 @@ ioctl_read_raw_toc(ioctl_t *ioctl) free(cur_full_toc); } -static void -ioctl_read_toc(ioctl_t *ioctl) -{ - ioctl_read_raw_toc(ioctl); -} - static int ioctl_get_track(const ioctl_t *ioctl, const uint32_t sector) { raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti; @@ -761,13 +755,13 @@ ioctl_load(const void *local) { const ioctl_t *ioctl = (const ioctl_t *) local; - if (ioctl_open_handle((ioctl_t *) ioctl)) { - long size; - DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, - NULL, 0, NULL, 0, - (LPDWORD) &size, NULL); + if ((ioctl->handle != NULL) || ioctl_open_handle((ioctl_t *) ioctl)) { + long size = 0; + (void) DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA, + NULL, 0, NULL, 0, + (LPDWORD) &size, NULL); - ioctl_read_toc((ioctl_t *) ioctl); + ioctl_read_raw_toc((ioctl_t *) ioctl); } } From 48f42af74575144d19a1cb7d005dad25a6cfe332 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 10:31:12 +0100 Subject: [PATCH 009/158] Moved some files to the utils folder, that's where the CRC code is soon going to reside as well. --- src/CMakeLists.txt | 10 +++------- src/utils/CMakeLists.txt | 25 +++++++++++++++++++++++++ src/{ => utils}/cJSON.c | 0 src/{ => utils}/fifo.c | 0 src/{ => utils}/fifo8.c | 0 src/{ => utils}/ini.c | 0 src/{ => utils}/log.c | 0 src/{ => utils}/random.c | 0 8 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 src/utils/CMakeLists.txt rename src/{ => utils}/cJSON.c (100%) rename src/{ => utils}/fifo.c (100%) rename src/{ => utils}/fifo8.c (100%) rename src/{ => utils}/ini.c (100%) rename src/{ => utils}/log.c (100%) rename src/{ => utils}/random.c (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7d6daff9c..3ae7c297e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,8 +23,6 @@ endif() add_executable(86Box 86box.c config.c - log.c - random.c timer.c io.c acpi.c @@ -41,15 +39,11 @@ add_executable(86Box pci.c mca.c usb.c - fifo.c - fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c machine_status.c - ini.c - cJSON.c ) if(CMAKE_SYSTEM_NAME MATCHES "Linux") @@ -106,7 +100,7 @@ if(INSTRUMENT) endif() target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd - net print scsi sio snd vid voodoo plat ui) + net print scsi sio snd utils vid voodoo plat ui) if(WIN32 AND ARCH STREQUAL "i386") if(MINGW) @@ -253,7 +247,9 @@ add_subdirectory(printer) add_subdirectory(sio) add_subdirectory(scsi) add_subdirectory(sound) +add_subdirectory(utils) add_subdirectory(video) + if (APPLE) add_subdirectory(mac) endif() diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt new file mode 100644 index 000000000..1d4b1f73e --- /dev/null +++ b/src/utils/CMakeLists.txt @@ -0,0 +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. +# +# CMake build script. +# +# Authors: David Hrdlička, +# Jasmine Iwanek, +# +# Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. +# + +add_library(utils OBJECT + cJSON.c + fifo.c + fifo8.c + ini.c + log.c + random.c +) diff --git a/src/cJSON.c b/src/utils/cJSON.c similarity index 100% rename from src/cJSON.c rename to src/utils/cJSON.c diff --git a/src/fifo.c b/src/utils/fifo.c similarity index 100% rename from src/fifo.c rename to src/utils/fifo.c diff --git a/src/fifo8.c b/src/utils/fifo8.c similarity index 100% rename from src/fifo8.c rename to src/utils/fifo8.c diff --git a/src/ini.c b/src/utils/ini.c similarity index 100% rename from src/ini.c rename to src/utils/ini.c diff --git a/src/log.c b/src/utils/log.c similarity index 100% rename from src/log.c rename to src/utils/log.c diff --git a/src/random.c b/src/utils/random.c similarity index 100% rename from src/random.c rename to src/utils/random.c From 1a33a2bd099763d577d0178d25240374184494c1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 19:47:21 +0100 Subject: [PATCH 010/158] CD-ROM: Ignore zero-length pages on MODE SELECT, and also stop properly on error. TODO: Apply to SCSI Disk, ZIP, and MO as well. --- src/scsi/scsi_cdrom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 8c24c4623..5d9a6e2f2 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -3672,12 +3672,17 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) pos += 2; + /* Ignore any page codes with zero length. */ + if (page_len == 0) + continue; + if (dev->drv->is_sony && (page == 0x08) && (page_len == 0x02)) dev->drv->sony_msf = dev->buffer[pos] & 0x01; if (!(dev->ms_page_flags & (1LL << ((uint64_t) page)))) { scsi_cdrom_log(dev->log, "Unimplemented page %02X\n", page); error |= 1; + break; } else { for (i = 0; i < page_len; i++) { uint8_t pg = page; @@ -3698,9 +3703,13 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) "%02X on page %02X\n", i + 2, page); scsi_cdrom_invalid_field_pl(dev, val); error |= 1; + break; } } } + + if (error) + break; } pos += page_len; @@ -3716,6 +3725,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc) if (error) { scsi_cdrom_buf_free(dev); + scsi_cdrom_command_stop((scsi_common_t *) dev); return 0; } break; From da360ab9da6a5ca4e8a38f912e564529efa5dc6c Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 13 Feb 2025 23:37:27 +0100 Subject: [PATCH 011/158] IOCTL: Fix detection of whether or not the disc has audio, fixes audio playing. --- src/cdrom/cdrom.c | 12 +++---- src/qt/win_cdrom_ioctl.c | 69 +++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index b34b01fff..8d6326f8b 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -431,8 +431,6 @@ read_toc_normal(const cdrom_t *dev, unsigned char *b, cdrom_log(dev->log, "read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i, %i)\n", (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); - pclog("read_toc_normal(%016" PRIXPTR ", %016" PRIXPTR ", %02X, %i, %i)\n", - (uintptr_t) dev, (uintptr_t) b, start_track, msf, sony); dev->ops->get_raw_track_info(dev->local, &num, rti); @@ -1848,9 +1846,9 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) b[10] = (dat >> 8) & 0xff; b[11] = dat & 0xff; } - pclog("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - b[ 0], b[ 1], b[ 2], b[ 3], b[ 4], b[ 5], b[ 6], b[ 7], - b[ 8], b[ 9], b[10], b[11]); + // pclog("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + // b[ 0], b[ 1], b[ 2], b[ 3], b[ 4], b[ 5], b[ 6], b[ 7], + // b[ 8], b[ 9], b[10], b[11]); if (b[0] != 0x00) break; base += 12; @@ -3074,7 +3072,9 @@ cdrom_reload(const uint8_t id) { cdrom_t *dev = &cdrom[id]; - if ((strcmp(dev->image_path, dev->prev_image_path) == 0) || (strlen(dev->prev_image_path) == 0) || (strlen(dev->image_path) > 0)) { + if ((strcmp(dev->image_path, dev->prev_image_path) == 0) || + (strlen(dev->prev_image_path) == 0) || + (strlen(dev->image_path) > 0)) { /* Switch from empty to empty. Do nothing. */ return; } diff --git a/src/qt/win_cdrom_ioctl.c b/src/qt/win_cdrom_ioctl.c index 40addd591..9af59190b 100644 --- a/src/qt/win_cdrom_ioctl.c +++ b/src/qt/win_cdrom_ioctl.c @@ -43,7 +43,6 @@ typedef struct ioctl_t { void *log; int is_dvd; int has_audio; - int32_t tracks_num; int blocks_num; uint8_t cur_rti[65536]; HANDLE handle; @@ -107,13 +106,13 @@ ioctl_open_handle(ioctl_t *ioctl) } static int -ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) +ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf, int32_t *tracks_num) { long size = 0; PCDROM_TOC_FULL_TOC_DATA cur_full_toc = NULL; CDROM_READ_TOC_EX cur_read_toc_ex = { 0 }; - ioctl->tracks_num = 0; + *tracks_num = 0; memset(toc_buf, 0x00, 65536); cur_full_toc = (PCDROM_TOC_FULL_TOC_DATA) calloc(1, 65536); @@ -132,7 +131,7 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) if (temp != 0) { const int length = ((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) + 2; memcpy(toc_buf, cur_full_toc, length); - ioctl->tracks_num = (length - 4) / 8; + *tracks_num = (length - 4) / 8; } free(cur_full_toc); @@ -141,9 +140,9 @@ ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf) PCDROM_TOC toc = (PCDROM_TOC) toc_buf; ioctl_log(ioctl->log, "%i tracks: %02X %02X %02X %02X\n", - ioctl->tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]); + *tracks_num, toc_buf[0], toc_buf[1], toc_buf[2], toc_buf[3]); - for (int i = 0; i < ioctl->tracks_num; i++) { + for (int i = 0; i < *tracks_num; i++) { const uint8_t *t = (const uint8_t *) &toc->TrackData[i]; ioctl_log(ioctl->log, "Track %03i: %02X %02X %02X %02X %02X %02X %02X %02X\n", i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]); @@ -185,7 +184,7 @@ ioctl_read_raw_toc(ioctl_t *ioctl) ioctl_log(ioctl->log, "status = %i\n", status); } - if ((status == 0) && (ioctl->tracks_num >= 1)) { + if (status == 0) { /* This is needed because in some circumstances (eg. a DVD .MDS mounted in Daemon Tools), reading the raw TOC fails but @@ -193,48 +192,54 @@ ioctl_read_raw_toc(ioctl_t *ioctl) raw TOC from the cooked TOC. */ uint8_t cur_toc[65536] = { 0 }; + int32_t tracks_num = 0; const CDROM_TOC * toc = (const CDROM_TOC *) cur_toc; - const TRACK_DATA *ct = &(toc->TrackData[ioctl->tracks_num - 1]); - ioctl_read_normal_toc(ioctl, cur_toc); + status = ioctl_read_normal_toc(ioctl, cur_toc, &tracks_num); - rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); - rti[0].point = 0xa0; - rti[0].pm = toc->FirstTrack; + const TRACK_DATA *ct = &(toc->TrackData[tracks_num - 1]); - rti[1].adr_ctl = rti[0].adr_ctl; - rti[1].point = 0xa1; - rti[1].pm = toc->LastTrack; + if ((status > 0) && (tracks_num >= 1)) { + rti[0].adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); + rti[0].point = 0xa0; + rti[0].pm = toc->FirstTrack; - rti[2].adr_ctl = rti[0].adr_ctl; - rti[2].point = 0xa2; - rti[2].pm = ct->Address[1]; - rti[2].ps = ct->Address[2]; - rti[2].pf = ct->Address[3]; + rti[1].adr_ctl = rti[0].adr_ctl; + rti[1].point = 0xa1; + rti[1].pm = toc->LastTrack; - ioctl->blocks_num = 3; + rti[2].adr_ctl = rti[0].adr_ctl; + rti[2].point = 0xa2; + rti[2].pm = ct->Address[1]; + rti[2].ps = ct->Address[2]; + rti[2].pf = ct->Address[3]; - for (int i = 0; i < (ioctl->tracks_num - 1); i++) { - raw_track_info_t *crt = &(rti[ioctl->blocks_num]); + ioctl->blocks_num = 3; - ct = &(toc->TrackData[i]); + for (int i = 0; i < (tracks_num - 1); i++) { + raw_track_info_t *crt = &(rti[ioctl->blocks_num]); - crt->adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); - crt->point = ct->TrackNumber; - crt->pm = ct->Address[1]; - crt->ps = ct->Address[2]; - crt->pf = ct->Address[3]; + ct = &(toc->TrackData[i]); - ioctl->blocks_num++; - } + crt->adr_ctl = ((ct->Adr & 0xf) << 4) | (ct->Control & 0xf); + crt->point = ct->TrackNumber; + crt->pm = ct->Address[1]; + crt->ps = ct->Address[2]; + crt->pf = ct->Address[3]; + + ioctl->blocks_num++; + } + } else if (status > 0) + /* Announce that we've had a failure. */ + status = 0; } else if (status != 0) { ioctl->blocks_num = (((cur_full_toc->Length[0] << 8) | cur_full_toc->Length[1]) - 2) / 11; memcpy(ioctl->cur_rti, cur_full_toc->Descriptors, ioctl->blocks_num * 11); } - if (ioctl->blocks_num) for (int i = 0; i < ioctl->tracks_num; i++) { + if (ioctl->blocks_num) for (int i = 0; i < ioctl->blocks_num; i++) { const raw_track_info_t *crt = &(rti[i]); if ((crt->point >= 1) && (crt->point <= 99) && !(crt->adr_ctl & 0x04)) { From ee2b523653afd6c0f4237d231004c58cead4c433 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 01:02:13 +0100 Subject: [PATCH 012/158] Fixed two warnings. --- src/scsi/scsi_cdrom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 5d9a6e2f2..840bec6a0 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -91,7 +91,7 @@ uint8_t scsi_cdrom_command_flags[0x100] = { eventually becomes ready, make the condition go away. */ [0x43 ... 0x45] = IMPLEMENTED | CHECK_READY, - [0x46] IMPLEMENTED | ALLOW_UA, + [0x46] = IMPLEMENTED | ALLOW_UA, [0x47 ... 0x49] = IMPLEMENTED | CHECK_READY, [0x4a] = IMPLEMENTED | ALLOW_UA, [0x4b] = IMPLEMENTED | CHECK_READY, @@ -664,7 +664,7 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) static void scsi_cdrom_set_period(scsi_cdrom_t *dev) { - const uint8_t cmd = dev->current_cdb[0]; + // const uint8_t cmd = dev->current_cdb[0]; scsi_cdrom_log(dev->log, "Current speed: %ix\n", dev->drv->cur_speed); From 1a0cefc3b395c0f0122cfb5626b7001cb1fb6185 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 03:29:35 +0100 Subject: [PATCH 013/158] And some more. --- src/cdrom/cdrom.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 8d6326f8b..9349223db 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1239,7 +1239,7 @@ cdrom_get_from_name(const char *s) wchar_t tempmsg[2048]; sprintf(n, "WARNING: CD-ROM \"%s\" not found - contact 86Box support\n", s); swprintf(tempmsg, sizeof_w(tempmsg), L"%hs", n); - pclog(n); + pclog("%s", n); ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), tempmsg); @@ -1571,7 +1571,7 @@ cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, dev->seek_pos = pos2; break; - } case 0x80: + } case 0x80: { track_info_t ti; pos2 = (pos2 >> 24) & 0xff; @@ -1586,7 +1586,7 @@ cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos, cdrom_stop(dev); } break; - default: + } default: break; } @@ -1689,7 +1689,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) pos2 = MSFtoLBA(m, s, f) - 150; dev->cd_end = pos2; break; - } case 0x80: + } case 0x80: { track_info_t ti; pos2 = (pos2 >> 24) & 0xff; @@ -1704,7 +1704,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type) cdrom_stop(dev); } break; - case 0xc0: + } case 0xc0: if (pos == 0xffffffff) { cdrom_log(dev->log, "Playing from current position\n"); pos2 = dev->cd_end; From 51185745648813c1e07feaf178b325ce691af9b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:06:20 +0100 Subject: [PATCH 014/158] Attempt to resolve again. --- src/video/vid_svga.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 7c674e00a..86173adef 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1543,8 +1543,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); - /* The chances of ever seeing a C-BUS (S)VGA card are approximately zero, but you never know. */ - } else if ((info->flags & DEVICE_CBUS) || (info->flags & DEVICE_ISA16)) { + } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_ISA16)) { svga->read = svga_read; svga->readw = svga_readw; svga->readl = NULL; From 7b1326236c0f967049664d8cc4bfa6b420d15bc4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:06:58 +0100 Subject: [PATCH 015/158] Tabs. --- src/video/vid_svga.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 86173adef..ffca0037f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1543,6 +1543,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); + /* The chances of ever seeing a C-BUS (S)VGA card are approximately zero, but you never know. */ } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_ISA16)) { svga->read = svga_read; svga->readw = svga_readw; From 4e1926f954fb5a6dd033dffa209405b181de1d58 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Feb 2025 09:11:49 +0100 Subject: [PATCH 016/158] The last time. --- src/video/vid_svga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index ffca0037f..7c674e00a 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1544,7 +1544,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); /* The chances of ever seeing a C-BUS (S)VGA card are approximately zero, but you never know. */ - } else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_ISA16)) { + } else if ((info->flags & DEVICE_CBUS) || (info->flags & DEVICE_ISA16)) { svga->read = svga_read; svga->readw = svga_readw; svga->readl = NULL; From c6dfd688f4dd8516e611b388fc5c53740deddefd Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 15 Feb 2025 07:09:14 +0100 Subject: [PATCH 017/158] Split off the CRC code to its own module. --- src/floppy/fdd_86f.c | 73 +++++++++++++++---------------------- src/include/86box/crc.h | 34 ++++++++++++++++++ src/include/86box/fdd.h | 15 ++------ src/utils/CMakeLists.txt | 1 + src/utils/crc.c | 77 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 57 deletions(-) create mode 100644 src/include/86box/crc.h create mode 100644 src/utils/crc.c diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 140e87899..f5626e35b 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -28,6 +28,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> +#include <86box/crc.h> #include <86box/dma.h> #include <86box/nvr.h> #include <86box/random.h> @@ -223,6 +224,7 @@ typedef struct d86f_t { uint8_t *filebuf; uint8_t *outbuf; sector_t *last_side_sector[2]; + uint16_t crc_table[256]; } d86f_t; static const uint8_t encoded_fm[64] = { @@ -247,7 +249,6 @@ static const uint8_t encoded_mfm[64] = { }; static d86f_t *d86f[FDD_NUM]; -static uint16_t CRCTable[256]; static fdc_t *d86f_fdc; uint64_t poly = 0x42F0E1EBA9EA3693LL; /* ECMA normal */ @@ -276,28 +277,6 @@ d86f_log(const char *fmt, ...) # define d86f_log(fmt, ...) #endif -static void -setup_crc(uint16_t poly) -{ - int c = 256; - int bc; - uint16_t temp; - - while (c--) { - temp = c << 8; - bc = 8; - - while (bc--) { - if (temp & 0x8000) - temp = (temp << 1) ^ poly; - else - temp <<= 1; - - CRCTable[c] = temp; - } - } -} - void d86f_destroy_linked_lists(int drive, int side) { @@ -1237,16 +1216,10 @@ decodefm(UNUSED(int drive), uint16_t dat) return temp; } -void -fdd_calccrc(uint8_t byte, crc_t *crc_var) -{ - crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8) ^ byte]; -} - static void d86f_calccrc(d86f_t *dev, uint8_t byte) { - fdd_calccrc(byte, &(dev->calc_crc)); + crc16_calc(dev->crc_table, byte, &(dev->calc_crc)); } int @@ -1274,7 +1247,9 @@ d86f_word_is_aligned(int drive, int side, uint32_t base_pos) /* State 1: Find sector ID */ void -d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, uint16_t other_am, uint16_t wrong_am, uint16_t ignore_other_am) +d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, + uint16_t other_am, uint16_t wrong_am, + uint16_t ignore_other_am) { d86f_t *dev = d86f[drive]; @@ -1282,7 +1257,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui if (dev->last_word[side] == req_am) { dev->calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]), + &(dev->calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; @@ -1302,7 +1278,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui if ((ignore_other_am & 2) && (dev->last_word[side] == other_am)) { dev->calc_crc.word = 0xFFFF; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]), + &(dev->calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) { @@ -1378,7 +1355,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u if ((dev->last_word[side] == req_am) && (find->sync_marks >= 3)) { if (d86f_word_is_aligned(drive, side, find->sync_pos)) { dev->calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]), + &(dev->calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; dev->preceding_bit[side] = dev->last_word[side] & 1; @@ -1390,7 +1368,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u if ((ignore_other_am & 2) && (dev->last_word[side] == other_am) && (find->sync_marks >= 3)) { if (d86f_word_is_aligned(drive, side, find->sync_pos)) { dev->calc_crc.word = 0xCDB4; - fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc)); + crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]), + &(dev->calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) { @@ -1464,8 +1443,11 @@ d86f_read_sector_id(int drive, int side, int match) if (dev->id_find.bytes_obtained < 4) { dev->last_sector.byte_array[dev->id_find.bytes_obtained] = decodefm(drive, dev->last_word[side]); - fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc)); - } else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) { + crc16_calc(dev->crc_table, + dev->last_sector.byte_array[dev->id_find.bytes_obtained], + &(dev->calc_crc)); + } else if ((dev->id_find.bytes_obtained >= 4) && + (dev->id_find.bytes_obtained < 6)) { dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] = decodefm(drive, dev->last_word[side]); } @@ -1643,7 +1625,7 @@ d86f_read_sector_data(int drive, int side) } } } - fdd_calccrc(data, &(dev->calc_crc)); + crc16_calc(dev->crc_table, data, &(dev->calc_crc)); } else if (dev->data_find.bytes_obtained < crc_pos) dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] = decodefm(drive, dev->last_word[side]); @@ -1730,11 +1712,12 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) if (dev->data_find.bytes_obtained < sector_len) { /* This is a data byte, so CRC it. */ - if (!dev->data_find.bytes_obtained) { - fdd_calccrc(decodefm(drive, am), &(dev->calc_crc)); - } else { - fdd_calccrc(dev->current_byte[side], &(dev->calc_crc)); - } + if (!dev->data_find.bytes_obtained) + crc16_calc(dev->crc_table, decodefm(drive, am), + &(dev->calc_crc)); + else + crc16_calc(dev->crc_table, dev->current_byte[side], + &(dev->calc_crc)); } } } else { @@ -3861,8 +3844,6 @@ d86f_load(int drive, char *fn) void d86f_init(void) { - setup_crc(0x1021); - for (uint8_t i = 0; i < FDD_NUM; i++) d86f[i] = NULL; } @@ -3926,6 +3907,8 @@ d86f_setup(int drive) dev->last_side_sector[0] = NULL; dev->last_side_sector[1] = NULL; + crc16_setup(dev->crc_table, 0x1021); + /* Set the drive as active. */ d86f[drive] = dev; } diff --git a/src/include/86box/crc.h b/src/include/86box/crc.h new file mode 100644 index 000000000..1a6e76dab --- /dev/null +++ b/src/include/86box/crc.h @@ -0,0 +1,34 @@ +/* + * 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. + * + * Definitions for the CRC code. + * + * Authors: Miran Grca, + * + * Copyright 2016-2025 Miran Grca. + */ +#ifndef EMU_CRC_H +#define EMU_CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { + uint16_t word; + uint8_t bytes[2]; +} crc_t; + +extern void crc16_setup(uint16_t *crc_table, uint16_t poly); +extern void crc16_calc(uint16_t *crc_table, uint8_t byte, crc_t *crc_var); + +#ifdef __cplusplus +} +#endif + +#endif /*EMU_CRC_H*/ diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index ff9315f1d..d6ade3bc6 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -8,15 +8,13 @@ * * Definitions for the floppy drive emulation. * - * - * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 Fred N. van Kempen. + * Copyright 2008-2025 Sarah Walker. + * Copyright 2016-2025 Miran Grca. + * Copyright 2018-2025 Fred N. van Kempen. */ #ifndef EMU_FDD_H #define EMU_FDD_H @@ -129,13 +127,6 @@ extern int drive_empty[FDD_NUM]; #define SECTOR_FIRST -2 #define SECTOR_NEXT -1 -typedef union { - uint16_t word; - uint8_t bytes[2]; -} crc_t; - -void fdd_calccrc(uint8_t byte, crc_t *crc_var); - typedef struct d86f_handler_t { uint16_t (*disk_flags)(int drive); uint16_t (*side_flags)(int drive); diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 1d4b1f73e..2ffe41f7b 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(utils OBJECT cJSON.c + crc.c fifo.c fifo8.c ini.c diff --git a/src/utils/crc.c b/src/utils/crc.c new file mode 100644 index 000000000..096a94c72 --- /dev/null +++ b/src/utils/crc.c @@ -0,0 +1,77 @@ +/* + * 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. + * + * CRC implementation. + * + * Authors: Miran Grca, + * + * Copyright 2016-2025 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/dma.h> +#include <86box/nvr.h> +#include <86box/random.h> +#include <86box/plat.h> +#include <86box/ui.h> +#include <86box/crc.h> + +#ifdef ENABLE_CRC_LOG +int d86f_do_log = ENABLE_CRC_LOG; + +static void +crc_log(const char *fmt, ...) +{ + va_list ap; + + if (crc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define crc_log(fmt, ...) +#endif + +void +crc16_setup(uint16_t *crc_table, uint16_t poly) +{ + int c = 256; + int bc; + uint16_t temp; + + while (c--) { + temp = c << 8; + bc = 8; + + while (bc--) { + if (temp & 0x8000) + temp = (temp << 1) ^ poly; + else + temp <<= 1; + + crc_table[c] = temp; + } + } +} + +void +crc16_calc(uint16_t *crc_table, uint8_t byte, crc_t *crc_var) +{ + crc_var->word = (crc_var->word << 8) ^ + crc_table[(crc_var->word >> 8) ^ byte]; +} From a62a6594e6d437b88bcc46bfc65c2688497dce64 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 5 Mar 2025 23:48:47 +0100 Subject: [PATCH 018/158] SCSI CD-ROM: Fixed SCSI standard reporting in INQUIRY. --- src/scsi/scsi_cdrom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 840bec6a0..0626fbee9 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -3444,7 +3444,8 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) dev->buffer[1] = 0x80; /* Removable */ if (dev->drv->bus_type == CDROM_BUS_SCSI) { - dev->buffer[3] = cdrom_get_scsi_std(dev->drv->type); + dev->buffer[2] = (dev->ven_cmd == scsi_cdrom_command_nec) ? + 0x00 : cdrom_get_scsi_std(dev->drv->type); if (dev->drv->is_toshiba) /* Linked Command and Relative Addressing supported */ From 4be691afe76181f3a885a3626bc814219a805424 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 01:44:02 +0100 Subject: [PATCH 019/158] IDE: Correctly terminate ATAPI command on DMA underrun, fixes Windows 9x freezes. --- src/disk/hdc_ide.c | 19 +++++++++++++------ src/scsi/scsi_cdrom.c | 1 - 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index afc466644..eb160c41b 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -241,7 +241,6 @@ int ide_qua_enabled = 0; static void ide_atapi_callback(ide_t *ide); static void ide_callback(void *priv); -// #define ENABLE_IDE_LOG 1 #ifdef ENABLE_IDE_LOG int ide_do_log = ENABLE_IDE_LOG; @@ -1092,12 +1091,16 @@ ide_atapi_callback(ide_t *ide) ide_irq_raise(ide); break; case PHASE_DATA_IN_DMA: - // pclog("Reading block %i... ", ide->sc->sector_len + 1); + // pclog("Reading block %i (%i, %i)... ", ide->sc->sector_len + 1, ide->sc->block_len, ide->sc->packet_len); if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { - if (ide->sc->block_len == 0) + if (ide->sc->block_len == 0) { ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, bm->priv); - else { + + /* Underrun. */ + if (ret == 1) + ret = 3; + } else { ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos - ide->sc->block_len, ide->sc->block_len, 0, bm->priv); @@ -1145,9 +1148,13 @@ ide_atapi_callback(ide_t *ide) case PHASE_DATA_OUT_DMA: if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { - if (ide->sc->block_len == 0) + if (ide->sc->block_len == 0) { ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 1, bm->priv); - else { + + /* Underrun. */ + if (ret == 1) + ret = 3; + } else { ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos, ide->sc->block_len, 1, bm->priv); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 0626fbee9..c505d9f53 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -15,7 +15,6 @@ */ #include #include -// #define ENABLE_SCSI_CDROM_LOG 2 #ifdef ENABLE_SCSI_CDROM_LOG #include #endif From a1996e79553ee41df49c30551403f5fd19bbd534 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 15 Mar 2025 01:09:41 +0700 Subject: [PATCH 020/158] Readd XT and AT floppy controllers They got removed during the addition of CompatiCard --- src/floppy/fdc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 5de1a8ef4..51c3aa24a 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -105,6 +105,8 @@ static fdc_cards_t fdc_cards[] = { // clang-format off { &device_none }, { &device_internal }, + { &fdc_xt_device }, + { &fdc_at_device }, { &fdc_b215_device }, { &fdc_pii151b_device }, { &fdc_pii158b_device }, From a340f250f2f27f229d3aff30272d62a0b676d859 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 15 Mar 2025 00:34:36 +0600 Subject: [PATCH 021/158] Attempt detecting BOM before parsing parameters --- src/qt/qt_glsl_parser.cpp | 36 ++++++++++++++++++++++--- src/qt/qt_openglshadermanagerdialog.cpp | 3 +++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 9a0a0fc03..e5c7b77f2 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -17,6 +17,7 @@ extern "C" #include <86box/config.h> #include <86box/qt-glslp-parser.h> #include <86box/path.h> +#include <86box/plat.h> extern void startblit(); extern void endblit(); @@ -81,14 +82,38 @@ static int endswith(const char *str, const char *ext) { return 0; } +static int +glsl_detect_bom(const char *fn) +{ + FILE *fp; + unsigned char bom[4] = { 0, 0, 0, 0 }; + + fp = plat_fopen(fn, "rb"); + if (fp == NULL) + return 0; + (void) !fread(bom, 1, 3, fp); + if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) { + fclose(fp); + return 1; + } + fclose(fp); + return 0; +} + static char *load_file(const char *fn) { - FILE *f = fopen(fn, "rb"); + int bom = glsl_detect_bom(fn); + FILE *f = plat_fopen(fn, "rb"); if (!f) return 0; fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); + if (bom) { + fsize -= 3; + fseek(f, 3, SEEK_SET); + } + char *data = (char*)malloc(fsize + 1); fread(data, fsize, 1, f); @@ -131,12 +156,15 @@ static int get_parameters(glslp_t *glsl) { int i; struct parameter p; for (i = 0; i < glsl->num_shaders; ++i) { + char line[1024]; struct shader *shader = &glsl->shaders[i]; - FILE *f = fopen(shader->shader_fn, "rb"); + int bom = glsl_detect_bom(shader->shader_fn); + FILE *f = plat_fopen(shader->shader_fn, "rb"); if (!f) return 0; - - char line[1024]; + if (bom) { + fseek(f, 3, SEEK_SET); + } while (fgets(line, sizeof(line) - 1, f) && glsl->num_parameters < MAX_PARAMETERS) { int num = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", p.id, p.description, &p.default_value, &p.min, &p.max, &p.step); diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 7f8a19414..72f58f9cb 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -63,6 +63,7 @@ OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) } else { ui->buttonConfigure->setEnabled(false); } + ui->buttonAdd->setDisabled(ui->shaderListWidget->count() >= MAX_USER_SHADERS); } else { ui->buttonRemove->setDisabled(true); ui->buttonMoveUp->setDisabled(true); @@ -177,6 +178,7 @@ void OpenGLShaderManagerDialog::on_buttonAdd_clicked() item->setData(Qt::UserRole + 2, (qulonglong)(uintptr_t)shaderfile); if (ui->shaderListWidget->count()) { ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); + ui->buttonAdd->setDisabled(ui->shaderListWidget->count() >= MAX_USER_SHADERS); } } else { QMessageBox::critical(this, tr("GLSL error"), tr("Could not load filename %1").arg(res)); @@ -197,6 +199,7 @@ void OpenGLShaderManagerDialog::on_buttonRemove_clicked() on_shaderListWidget_currentRowChanged(ui->shaderListWidget->currentRow()); } + ui->buttonAdd->setDisabled(ui->shaderListWidget->count() >= MAX_USER_SHADERS); } void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted() From b5c158ec98a02df1ea1ec559712601bd8ac4681a Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 14 Mar 2025 20:11:55 +0100 Subject: [PATCH 022/158] SCSI CD-ROM: Revert the performance-reducing changes to scsi_cdrom_command_common() introduced in build 6541. --- src/scsi/scsi_cdrom.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index cc9cc40c1..e16b16e7c 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -678,13 +678,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) dev->callback += period; scsi_cdrom_set_callback(dev); return; - case 0x43: - dev->drv->seek_diff = dev->drv->seek_pos + 150; - dev->drv->seek_pos = 0; - fallthrough; case 0x08: case 0x28: - case 0x42: case 0x44: case 0xa8: /* Seek time is in us. */ period = cdrom_seek_time(dev->drv); @@ -698,7 +693,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) dev->callback += period; fallthrough; case 0x25: - // case 0x42 ... 0x44: + case 0x42 ... 0x44: case 0x51 ... 0x52: case 0xad: case 0xb8 ... 0xb9: @@ -707,11 +702,6 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) dev->callback += 40.0; /* Account for seek time. */ /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ - /* - TODO: This is a bit of a lie - the actual period is closer to - 75 * 2448 bytes per second, because the subchannel data - has to be read as well. - */ bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; break; @@ -740,19 +730,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) period = 1000000.0 / bytes_per_second; scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", (uint64_t) period); - switch (cmd) { - default: - period = period * (double) (dev->packet_len); - break; - case 0x42: case 0x44: - /* READ SUBCHANNEL or READ HEADER - period of 1 entire sector. */ - period = period * 2352.0; - break; - case 0x43: - /* READ TOC - period of 175 entire frames. */ - period = period * 150.0 * 2352.0; - break; - } + period = period * (double) (dev->packet_len); scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); dev->callback += period; From 9af19f850ea0374f3cbd07e0b23b0857aba581e0 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 15 Mar 2025 13:17:14 +0600 Subject: [PATCH 023/158] Parse shader parameter lines with an alternate method --- src/qt/qt_glsl_parser.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index e5c7b77f2..fa45267a7 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -21,6 +21,8 @@ extern "C" extern void startblit(); extern void endblit(); +extern ssize_t local_getline(char **buf, size_t *bufsiz, FILE *fp); +extern char* trim(char* str); } #define safe_strncpy(a, b, n) \ @@ -156,7 +158,8 @@ static int get_parameters(glslp_t *glsl) { int i; struct parameter p; for (i = 0; i < glsl->num_shaders; ++i) { - char line[1024]; + size_t size = 0; + char* line = NULL; struct shader *shader = &glsl->shaders[i]; int bom = glsl_detect_bom(shader->shader_fn); FILE *f = plat_fopen(shader->shader_fn, "rb"); @@ -165,7 +168,9 @@ static int get_parameters(glslp_t *glsl) { if (bom) { fseek(f, 3, SEEK_SET); } - while (fgets(line, sizeof(line) - 1, f) && glsl->num_parameters < MAX_PARAMETERS) { + while (local_getline(&line, &size, f) != -1 && glsl->num_parameters < MAX_PARAMETERS) { + line[strcspn(line, "\r\n")] = '\0'; + trim(line); int num = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", p.id, p.description, &p.default_value, &p.min, &p.max, &p.step); if (num < 5) From 4a9b0e0df8a94287bef72644111df5caa7a38397 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 15 Mar 2025 13:17:41 +0600 Subject: [PATCH 024/158] Apply filter changes to the scene FBO texture as well --- src/qt/qt_openglrenderer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp index 3b2ec58e0..b465bfddd 100644 --- a/src/qt/qt_openglrenderer.cpp +++ b/src/qt/qt_openglrenderer.cpp @@ -1393,6 +1393,10 @@ OpenGLRenderer::render() glw.glBindTexture(GL_TEXTURE_2D, scene_texture.id); scene_texture.min_filter = scene_texture.mag_filter = video_filter_method ? GL_LINEAR : GL_NEAREST; + active_shader->scene.fbo.texture.min_filter = active_shader->scene.fbo.texture.mag_filter = video_filter_method ? GL_LINEAR : GL_NEAREST; + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, video_filter_method ? GL_LINEAR : GL_NEAREST); + glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, video_filter_method ? GL_LINEAR : GL_NEAREST); + glw.glBindTexture(GL_TEXTURE_2D, active_shader->scene.fbo.texture.id); glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, video_filter_method ? GL_LINEAR : GL_NEAREST); glw.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, video_filter_method ? GL_LINEAR : GL_NEAREST); glw.glBindTexture(GL_TEXTURE_2D, 0); From b8894fc9dfb403e0e723091c71aa21482321d52f Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Sat, 15 Mar 2025 15:13:02 +0200 Subject: [PATCH 025/158] Add files via upload Fixes broken translation of "About 86Box" --- src/qt/qt_mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index cdb46cb29..41654ab25 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1754,7 +1754,7 @@ MainWindow::on_actionAbout_86Box_triggered() versioninfo.append(QString(" [%1, %2]").arg(QSysInfo::buildCpuArchitecture(), tr(DYNAREC_STR))); msgBox.setText(QString("%3%1%2").arg(EMU_VERSION_FULL, versioninfo, tr("86Box v"))); msgBox.setInformativeText(tr("An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information.")); - msgBox.setWindowTitle("About 86Box"); + msgBox.setWindowTitle(tr("About 86Box")); const auto closeButton = msgBox.addButton("OK", QMessageBox::ButtonRole::AcceptRole); msgBox.setEscapeButton(closeButton); const auto webSiteButton = msgBox.addButton(EMU_SITE, QMessageBox::ButtonRole::HelpRole); From dcce23a7d3c53ea1b544d58dab02065200ffb3e5 Mon Sep 17 00:00:00 2001 From: usergithub64 <58270614+usergithub64@users.noreply.github.com> Date: Sat, 15 Mar 2025 15:13:55 +0200 Subject: [PATCH 026/158] Add files via upload Fixes broken translation of "Receive MIDI Input" for Ensoniq AudioPCI (ES1370) --- src/sound/snd_audiopci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 8d1de442b..1ca547650 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -2742,7 +2742,7 @@ static const device_config_t es1370_config[] = { // clang-format off { .name = "receive_input", - .description = "Receive input (MIDI)", + .description = "Receive MIDI input", .type = CONFIG_BINARY, .default_string = NULL, .default_int = 1, From 26e1852b5a22ff23e079f13619f8f8fd33b4f25f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 15 Mar 2025 23:47:10 +0600 Subject: [PATCH 027/158] Make renderer options item enabled/disabled instead Also a missed French translation --- src/qt/languages/fr-FR.po | 2 +- src/qt/qt.c | 5 ----- src/qt/qt_mainwindow.cpp | 5 +---- src/qt/qt_rendererstack.cpp | 22 +--------------------- src/qt/qt_rendererstack.hpp | 1 - 5 files changed, 3 insertions(+), 32 deletions(-) diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 3b283b3dd..590674a29 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -37,7 +37,7 @@ msgid "&Hide status bar" msgstr "&Masquer la barre de status" msgid "Hide &toolbar" -msgstr "Hide &toolbar" +msgstr "Masquer la &barre d'outils" msgid "&Resizeable window" msgstr "Fenètre &Retaillable" diff --git a/src/qt/qt.c b/src/qt/qt.c index 13ddbf498..a9a6460eb 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -54,8 +54,6 @@ plat_vidapi(const char *api) return 4; } else if (!strcasecmp(api, "vnc")) { return 5; - } else if (!strcasecmp(api, "qt_opengl3_pcem")) { - return 6; } return 0; @@ -85,9 +83,6 @@ plat_vidapi_name(int api) case 5: name = "vnc"; break; - case 6: - name = "qt_opengl3_pcem"; - break; default: fatal("Unknown renderer: %i\n", api); break; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index cdb46cb29..d2c4667cd 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -454,9 +454,6 @@ MainWindow::MainWindow(QWidget *parent) endblit(); } #endif - case 6: - newVidApi = RendererStack::Renderer::OpenGL3PCem; - break; } ui->stackedWidget->switchRenderer(newVidApi); if (!show_second_monitors) @@ -468,7 +465,7 @@ MainWindow::MainWindow(QWidget *parent) }); connect(ui->stackedWidget, &RendererStack::rendererChanged, [this]() { - ui->actionRenderer_options->setVisible(ui->stackedWidget->hasOptions()); + ui->actionRenderer_options->setEnabled(ui->stackedWidget->hasOptions()); }); /* Trigger initial renderer switch */ diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 43e696085..bd1fd2609 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -339,26 +339,6 @@ RendererStack::createRenderer(Renderer renderer) current.reset(this->createWindowContainer(hw, this)); break; } - case Renderer::OpenGL3PCem: - { - this->createWinId(); - auto hw = new OpenGLRenderer(this); - rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRenderer::initialized, [=]() { - /* Buffers are available only after initialization. */ - imagebufs = rendererWindow->getBuffers(); - endblit(); - emit rendererChanged(); - }); - connect(hw, &OpenGLRenderer::errorInitializing, [=]() { - /* Renderer not could initialize, fallback to software. */ - imagebufs = {}; - QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); - }); - current.reset(this->createWindowContainer(hw, this)); - break; - } case Renderer::OpenGL3: { this->createWinId(); @@ -431,7 +411,7 @@ RendererStack::createRenderer(Renderer renderer) currentBuf = 0; - if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::OpenGL3PCem) { + if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) { imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index a84773c72..309cae7f5 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -61,7 +61,6 @@ public: OpenGLES, OpenGL3, Vulkan, - OpenGL3PCem = 6, None = -1 }; void switchRenderer(Renderer renderer); From 000af483f3e0561fbb4c214496d20d0be358359b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 16 Mar 2025 01:46:34 +0600 Subject: [PATCH 028/158] C&T 69000: All ROPs now implemented, also fixed transparency bitblts Several optimizations also implemented --- src/video/vid_chips_69000.c | 1342 ++++++++++++++++++++++------------- 1 file changed, 833 insertions(+), 509 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index a387e99fa..b0e8db35a 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -251,486 +251,797 @@ chips_69000_bitblt_interrupt(chips_69000_t* chips) chips_69000_interrupt(chips); } -void -chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFF; - break; +#define ROPMIX(R, D, P, S, out) \ + { \ + switch (R) { \ + case 0x00: \ + out = 0; \ + break; \ + case 0x01: \ + out = ~(D | (P | S)); \ + break; \ + case 0x02: \ + out = D & ~(P | S); \ + break; \ + case 0x03: \ + out = ~(P | S); \ + break; \ + case 0x04: \ + out = S & ~(D | P); \ + break; \ + case 0x05: \ + out = ~(D | P); \ + break; \ + case 0x06: \ + out = ~(P | ~(D ^ S)); \ + break; \ + case 0x07: \ + out = ~(P | (D & S)); \ + break; \ + case 0x08: \ + out = S & (D & ~P); \ + break; \ + case 0x09: \ + out = ~(P | (D ^ S)); \ + break; \ + case 0x0a: \ + out = D & ~P; \ + break; \ + case 0x0b: \ + out = ~(P | (S & ~D)); \ + break; \ + case 0x0c: \ + out = S & ~P; \ + break; \ + case 0x0d: \ + out = ~(P | (D & ~S)); \ + break; \ + case 0x0e: \ + out = ~(P | ~(D | S)); \ + break; \ + case 0x0f: \ + out = ~P; \ + break; \ + case 0x10: \ + out = P & ~(D | S); \ + break; \ + case 0x11: \ + out = ~(D | S); \ + break; \ + case 0x12: \ + out = ~(S | ~(D ^ P)); \ + break; \ + case 0x13: \ + out = ~(S | (D & P)); \ + break; \ + case 0x14: \ + out = ~(D | ~(P ^ S)); \ + break; \ + case 0x15: \ + out = ~(D | (P & S)); \ + break; \ + case 0x16: \ + out = P ^ (S ^ (D & ~(P & S))); \ + break; \ + case 0x17: \ + out = ~(S ^ ((S ^ P) & (D ^ S))); \ + break; \ + case 0x18: \ + out = (S ^ P) & (P ^ D); \ + break; \ + case 0x19: \ + out = ~(S ^ (D & ~(P & S))); \ + break; \ + case 0x1a: \ + out = P ^ (D | (S & P)); \ + break; \ + case 0x1b: \ + out = ~(S ^ (D & (P ^ S))); \ + break; \ + case 0x1c: \ + out = P ^ (S | (D & P)); \ + break; \ + case 0x1d: \ + out = ~(D ^ (S & (P ^ D))); \ + break; \ + case 0x1e: \ + out = P ^ (D | S); \ + break; \ + case 0x1f: \ + out = ~(P & (D | S)); \ + break; \ + case 0x20: \ + out = D & (P & ~S); \ + break; \ + case 0x21: \ + out = ~(S | (D ^ P)); \ + break; \ + case 0x22: \ + out = D & ~S; \ + break; \ + case 0x23: \ + out = ~(S | (P & ~D)); \ + break; \ + case 0x24: \ + out = (S ^ P) & (D ^ S); \ + break; \ + case 0x25: \ + out = ~(P ^ (D & ~(S & P))); \ + break; \ + case 0x26: \ + out = S ^ (D | (P & S)); \ + break; \ + case 0x27: \ + out = S ^ (D | ~(P ^ S)); \ + break; \ + case 0x28: \ + out = D & (P ^ S); \ + break; \ + case 0x29: \ + out = ~(P ^ (S ^ (D | (P & S)))); \ + break; \ + case 0x2a: \ + out = D & ~(P & S); \ + break; \ + case 0x2b: \ + out = ~(S ^ ((S ^ P) & (P ^ D))); \ + break; \ + case 0x2c: \ + out = S ^ (P & (D | S)); \ + break; \ + case 0x2d: \ + out = P ^ (S | ~D); \ + break; \ + case 0x2e: \ + out = P ^ (S | (D ^ P)); \ + break; \ + case 0x2f: \ + out = ~(P & (S | ~D)); \ + break; \ + case 0x30: \ + out = P & ~S; \ + break; \ + case 0x31: \ + out = ~(S | (D & ~P)); \ + break; \ + case 0x32: \ + out = S ^ (D | (P | S)); \ + break; \ + case 0x33: \ + out = ~S; \ + break; \ + case 0x34: \ + out = S ^ (P | (D & S)); \ + break; \ + case 0x35: \ + out = S ^ (P | ~(D ^ S)); \ + break; \ + case 0x36: \ + out = S ^ (D | P); \ + break; \ + case 0x37: \ + out = ~(S & (D | P)); \ + break; \ + case 0x38: \ + out = P ^ (S & (D | P)); \ + break; \ + case 0x39: \ + out = S ^ (P | ~D); \ + break; \ + case 0x3a: \ + out = S ^ (P | (D ^ S)); \ + break; \ + case 0x3b: \ + out = ~(S & (P | ~D)); \ + break; \ + case 0x3c: \ + out = P ^ S; \ + break; \ + case 0x3d: \ + out = S ^ (P | ~(D | S)); \ + break; \ + case 0x3e: \ + out = S ^ (P | (D & ~S)); \ + break; \ + case 0x3f: \ + out = ~(P & S); \ + break; \ + case 0x40: \ + out = P & (S & ~D); \ + break; \ + case 0x41: \ + out = ~(D | (P ^ S)); \ + break; \ + case 0x42: \ + out = (S ^ D) & (P ^ D); \ + break; \ + case 0x43: \ + out = ~(S ^ (P & ~(D & S))); \ + break; \ + case 0x44: \ + out = S & ~D; \ + break; \ + case 0x45: \ + out = ~(D | (P & ~S)); \ + break; \ + case 0x46: \ + out = D ^ (S | (P & D)); \ + break; \ + case 0x47: \ + out = ~(P ^ (S & (D ^ P))); \ + break; \ + case 0x48: \ + out = S & (D ^ P); \ + break; \ + case 0x49: \ + out = ~(P ^ (D ^ (S | (P & D)))); \ + break; \ + case 0x4a: \ + out = D ^ (P & (S | D)); \ + break; \ + case 0x4b: \ + out = P ^ (D | ~S); \ + break; \ + case 0x4c: \ + out = S & ~(D & P); \ + break; \ + case 0x4d: \ + out = ~(S ^ ((S ^ P) | (D ^ S))); \ + break; \ + case 0x4e: \ + out = P ^ (D | (S ^ P)); \ + break; \ + case 0x4f: \ + out = ~(P & (D | ~S)); \ + break; \ + case 0x50: \ + out = P & ~D; \ + break; \ + case 0x51: \ + out = ~(D | (S & ~P)); \ + break; \ + case 0x52: \ + out = D ^ (P | (S & D)); \ + break; \ + case 0x53: \ + out = ~(S ^ (P & (D ^ S))); \ + break; \ + case 0x54: \ + out = ~(D | ~(P | S)); \ + break; \ + case 0x55: \ + out = ~D; \ + break; \ + case 0x56: \ + out = D ^ (P | S); \ + break; \ + case 0x57: \ + out = ~(D & (P | S)); \ + break; \ + case 0x58: \ + out = P ^ (D & (S | P)); \ + break; \ + case 0x59: \ + out = D ^ (P | ~S); \ + break; \ + case 0x5a: \ + out = D ^ P; \ + break; \ + case 0x5b: \ + out = D ^ (P | ~(S | D)); \ + break; \ + case 0x5c: \ + out = D ^ (P | (S ^ D)); \ + break; \ + case 0x5d: \ + out = ~(D & (P | ~S)); \ + break; \ + case 0x5e: \ + out = D ^ (P | (S & ~D)); \ + break; \ + case 0x5f: \ + out = ~(D & P); \ + break; \ + case 0x60: \ + out = P & (D ^ S); \ + break; \ + case 0x61: \ + out = ~(D ^ (S ^ (P | (D & S)))); \ + break; \ + case 0x62: \ + out = D ^ (S & (P | D)); \ + break; \ + case 0x63: \ + out = S ^ (D | ~P); \ + break; \ + case 0x64: \ + out = S ^ (D & (P | S)); \ + break; \ + case 0x65: \ + out = D ^ (S | ~P); \ + break; \ + case 0x66: \ + out = D ^ S; \ + break; \ + case 0x67: \ + out = S ^ (D | ~(P | S)); \ + break; \ + case 0x68: \ + out = ~(D ^ (S ^ (P | ~(D | S)))); \ + break; \ + case 0x69: \ + out = ~(P ^ (D ^ S)); \ + break; \ + case 0x6a: \ + out = D ^ (P & S); \ + break; \ + case 0x6b: \ + out = ~(P ^ (S ^ (D & (P | S)))); \ + break; \ + case 0x6c: \ + out = S ^ (D & P); \ + break; \ + case 0x6d: \ + out = ~(P ^ (D ^ (S & (P | D)))); \ + break; \ + case 0x6e: \ + out = S ^ (D & (P | ~S)); \ + break; \ + case 0x6f: \ + out = ~(P & ~(D ^ S)); \ + break; \ + case 0x70: \ + out = P & ~(D & S); \ + break; \ + case 0x71: \ + out = ~(S ^ ((S ^ D) & (P ^ D))); \ + break; \ + case 0x72: \ + out = S ^ (D | (P ^ S)); \ + break; \ + case 0x73: \ + out = ~(S & (D | ~P)); \ + break; \ + case 0x74: \ + out = D ^ (S | (P ^ D)); \ + break; \ + case 0x75: \ + out = ~(D & (S | ~P)); \ + break; \ + case 0x76: \ + out = S ^ (D | (P & ~S)); \ + break; \ + case 0x77: \ + out = ~(D & S); \ + break; \ + case 0x78: \ + out = P ^ (D & S); \ + break; \ + case 0x79: \ + out = ~(D ^ (S ^ (P & (D | S)))); \ + break; \ + case 0x7a: \ + out = D ^ (P & (S | ~D)); \ + break; \ + case 0x7b: \ + out = ~(S & ~(D ^ P)); \ + break; \ + case 0x7c: \ + out = S ^ (P & (D | ~S)); \ + break; \ + case 0x7d: \ + out = ~(D & ~(P ^ S)); \ + break; \ + case 0x7e: \ + out = (S ^ P) | (D ^ S); \ + break; \ + case 0x7f: \ + out = ~(D & (P & S)); \ + break; \ + case 0x80: \ + out = D & (P & S); \ + break; \ + case 0x81: \ + out = ~((S ^ P) | (D ^ S)); \ + break; \ + case 0x82: \ + out = D & ~(P ^ S); \ + break; \ + case 0x83: \ + out = ~(S ^ (P & (D | ~S))); \ + break; \ + case 0x84: \ + out = S & ~(D ^ P); \ + break; \ + case 0x85: \ + out = ~(P ^ (D & (S | ~P))); \ + break; \ + case 0x86: \ + out = D ^ (S ^ (P & (D | S))); \ + break; \ + case 0x87: \ + out = ~(P ^ (D & S)); \ + break; \ + case 0x88: \ + out = D & S; \ + break; \ + case 0x89: \ + out = ~(S ^ (D | (P & ~S))); \ + break; \ + case 0x8a: \ + out = D & (S | ~P); \ + break; \ + case 0x8b: \ + out = ~(D ^ (S | (P ^ D))); \ + break; \ + case 0x8c: \ + out = S & (D | ~P); \ + break; \ + case 0x8d: \ + out = ~(S ^ (D | (P ^ S))); \ + break; \ + case 0x8e: \ + out = S ^ ((S ^ D) & (P ^ D)); \ + break; \ + case 0x8f: \ + out = ~(P & ~(D & S)); \ + break; \ + case 0x90: \ + out = P & ~(D ^ S); \ + break; \ + case 0x91: \ + out = ~(S ^ (D & (P | ~S))); \ + break; \ + case 0x92: \ + out = D ^ (P ^ (S & (D | P))); \ + break; \ + case 0x93: \ + out = ~(S ^ (P & D)); \ + break; \ + case 0x94: \ + out = P ^ (S ^ (D & (P | S))); \ + break; \ + case 0x95: \ + out = ~(D ^ (P & S)); \ + break; \ + case 0x96: \ + out = D ^ (P ^ S); \ + break; \ + case 0x97: \ + out = P ^ (S ^ (D | ~(P | S))); \ + break; \ + case 0x98: \ + out = ~(S ^ (D | ~(P | S))); \ + break; \ + case 0x99: \ + out = ~(D ^ S); \ + break; \ + case 0x9a: \ + out = D ^ (P & ~S); \ + break; \ + case 0x9b: \ + out = ~(S ^ (D & (P | S))); \ + break; \ + case 0x9c: \ + out = S ^ (P & ~D); \ + break; \ + case 0x9d: \ + out = ~(D ^ (S & (P | D))); \ + break; \ + case 0x9e: \ + out = D ^ (S ^ (P | (D & S))); \ + break; \ + case 0x9f: \ + out = ~(P & (D ^ S)); \ + break; \ + case 0xa0: \ + out = D & P; \ + break; \ + case 0xa1: \ + out = ~(P ^ (D | (S & ~P))); \ + break; \ + case 0xa2: \ + out = D & (P | ~S); \ + break; \ + case 0xa3: \ + out = ~(D ^ (P | (S ^ D))); \ + break; \ + case 0xa4: \ + out = ~(P ^ (D | ~(S | P))); \ + break; \ + case 0xa5: \ + out = ~(P ^ D); \ + break; \ + case 0xa6: \ + out = D ^ (S & ~P); \ + break; \ + case 0xa7: \ + out = ~(P ^ (D & (S | P))); \ + break; \ + case 0xa8: \ + out = D & (P | S); \ + break; \ + case 0xa9: \ + out = ~(D ^ (P | S)); \ + break; \ + case 0xaa: \ + out = D; \ + break; \ + case 0xab: \ + out = D | ~(P | S); \ + break; \ + case 0xac: \ + out = S ^ (P & (D ^ S)); \ + break; \ + case 0xad: \ + out = ~(D ^ (P | (S & D))); \ + break; \ + case 0xae: \ + out = D | (S & ~P); \ + break; \ + case 0xaf: \ + out = D | ~P; \ + break; \ + case 0xb0: \ + out = P & (D | ~S); \ + break; \ + case 0xb1: \ + out = ~(P ^ (D | (S ^ P))); \ + break; \ + case 0xb2: \ + out = S ^ ((S ^ P) | (D ^ S)); \ + break; \ + case 0xb3: \ + out = ~(S & ~(D & P)); \ + break; \ + case 0xb4: \ + out = P ^ (S & ~D); \ + break; \ + case 0xb5: \ + out = ~(D ^ (P & (S | D))); \ + break; \ + case 0xb6: \ + out = D ^ (P ^ (S | (D & P))); \ + break; \ + case 0xb7: \ + out = ~(S & (D ^ P)); \ + break; \ + case 0xb8: \ + out = P ^ (S & (D ^ P)); \ + break; \ + case 0xb9: \ + out = ~(D ^ (S | (P & D))); \ + break; \ + case 0xba: \ + out = D | (P & ~S); \ + break; \ + case 0xbb: \ + out = D | ~S; \ + break; \ + case 0xbc: \ + out = S ^ (P & ~(D & S)); \ + break; \ + case 0xbd: \ + out = ~((S ^ D) & (P ^ D)); \ + break; \ + case 0xbe: \ + out = D | (P ^ S); \ + break; \ + case 0xbf: \ + out = D | ~(P & S); \ + break; \ + case 0xc0: \ + out = P & S; \ + break; \ + case 0xc1: \ + out = ~(S ^ (P | (D & ~S))); \ + break; \ + case 0xc2: \ + out = ~(S ^ (P | ~(D | S))); \ + break; \ + case 0xc3: \ + out = ~(P ^ S); \ + break; \ + case 0xc4: \ + out = S & (P | ~D); \ + break; \ + case 0xc5: \ + out = ~(S ^ (P | (D ^ S))); \ + break; \ + case 0xc6: \ + out = S ^ (D & ~P); \ + break; \ + case 0xc7: \ + out = ~(P ^ (S & (D | P))); \ + break; \ + case 0xc8: \ + out = S & (D | P); \ + break; \ + case 0xc9: \ + out = ~(S ^ (P | D)); \ + break; \ + case 0xca: \ + out = D ^ (P & (S ^ D)); \ + break; \ + case 0xcb: \ + out = ~(S ^ (P | (D & S))); \ + break; \ + case 0xcc: \ + out = S; \ + break; \ + case 0xcd: \ + out = S | ~(D | P); \ + break; \ + case 0xce: \ + out = S | (D & ~P); \ + break; \ + case 0xcf: \ + out = S | ~P; \ + break; \ + case 0xd0: \ + out = P & (S | ~D); \ + break; \ + case 0xd1: \ + out = ~(P ^ (S | (D ^ P))); \ + break; \ + case 0xd2: \ + out = P ^ (D & ~S); \ + break; \ + case 0xd3: \ + out = ~(S ^ (P & (D | S))); \ + break; \ + case 0xd4: \ + out = S ^ ((S ^ P) & (P ^ D)); \ + break; \ + case 0xd5: \ + out = ~(D & ~(P & S)); \ + break; \ + case 0xd6: \ + out = P ^ (S ^ (D | (P & S))); \ + break; \ + case 0xd7: \ + out = ~(D & (P ^ S)); \ + break; \ + case 0xd8: \ + out = P ^ (D & (S ^ P)); \ + break; \ + case 0xd9: \ + out = ~(S ^ (D | (P & S))); \ + break; \ + case 0xda: \ + out = D ^ (P & ~(S & D)); \ + break; \ + case 0xdb: \ + out = ~((S ^ P) & (D ^ S)); \ + break; \ + case 0xdc: \ + out = S | (P & ~D); \ + break; \ + case 0xdd: \ + out = S | ~D; \ + break; \ + case 0xde: \ + out = S | (D ^ P); \ + break; \ + case 0xdf: \ + out = S | ~(D & P); \ + break; \ + case 0xe0: \ + out = P & (D | S); \ + break; \ + case 0xe1: \ + out = ~(P ^ (D | S)); \ + break; \ + case 0xe2: \ + out = D ^ (S & (P ^ D)); \ + break; \ + case 0xe3: \ + out = ~(P ^ (S | (D & P))); \ + break; \ + case 0xe4: \ + out = S ^ (D & (P ^ S)); \ + break; \ + case 0xe5: \ + out = ~(P ^ (D | (S & P))); \ + break; \ + case 0xe6: \ + out = S ^ (D & ~(P & S)); \ + break; \ + case 0xe7: \ + out = ~((S ^ P) & (P ^ D)); \ + break; \ + case 0xe8: \ + out = S ^ ((S ^ P) & (D ^ S)); \ + break; \ + case 0xe9: \ + out = ~(D ^ (S ^ (P & ~(D & S)))); \ + break; \ + case 0xea: \ + out = D | (P & S); \ + break; \ + case 0xeb: \ + out = D | ~(P ^ S); \ + break; \ + case 0xec: \ + out = S | (D & P); \ + break; \ + case 0xed: \ + out = S | ~(D ^ P); \ + break; \ + case 0xee: \ + out = D | S; \ + break; \ + case 0xef: \ + out = S | (D | ~P); \ + break; \ + case 0xf0: \ + out = P; \ + break; \ + case 0xf1: \ + out = P | ~(D | S); \ + break; \ + case 0xf2: \ + out = P | (D & ~S); \ + break; \ + case 0xf3: \ + out = P | ~S; \ + break; \ + case 0xf4: \ + out = P | (S & ~D); \ + break; \ + case 0xf5: \ + out = P | ~D; \ + break; \ + case 0xf6: \ + out = P | (D ^ S); \ + break; \ + case 0xf7: \ + out = P | ~(D & S); \ + break; \ + case 0xf8: \ + out = P | (D & S); \ + break; \ + case 0xf9: \ + out = P | ~(D ^ S); \ + break; \ + case 0xfa: \ + out = D | P; \ + break; \ + case 0xfb: \ + out = D | (P | ~S); \ + break; \ + case 0xfc: \ + out = P | S; \ + break; \ + case 0xfd: \ + out = P | (S | ~D); \ + break; \ + case 0xfe: \ + out = D | (P | S); \ + break; \ + case 0xff: \ + out = ~0; \ + break; \ + } \ } -} - -void -chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFFFF; - break; - } -} - -void -chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFFFFFF; - break; - } -} void chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) { - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_8bpp(dst, src, rop); - } - - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - } + ROPMIX(rop, *dst, pattern, src, *dst); } void chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) { - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_16bpp(dst, src, rop); - } - - switch (rop) { - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - } + ROPMIX(rop, *dst, pattern, src, *dst); } void chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src, uint8_t rop) { uint32_t orig_dst = *dst & 0xFF000000; - - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_24bpp(dst, src, rop); - } - - switch (rop) { - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - } + ROPMIX(rop, *dst, pattern, src, *dst); *dst &= 0xFFFFFF; *dst |= orig_dst; } @@ -895,20 +1206,22 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - dest_pixel = chips_69000_readb_linear(dest_addr, chips); + //dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; break; } case 2: /* 16 bits-per-pixel. */ { - dest_pixel = chips_69000_readb_linear(dest_addr, chips); - dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + //dest_pixel = *(uint16_t*)&chips->svga.vram[dest_addr & chips->svga.vram_mask]; + dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; + dest_pixel |= chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] << 8; break; } case 3: /* 24 bits-per-pixel. */ { - dest_pixel = chips_69000_readb_linear(dest_addr, chips); - dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; - dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16; + dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; + dest_pixel |= chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] << 8; + dest_pixel |= chips->svga.vram[(dest_addr + 2) & chips->svga.vram_mask] << 16; break; } } @@ -921,7 +1234,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) pattern_data = 0; else - pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); + pattern_data = chips->svga.vram[(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7)) & chips->svga.vram_mask]; //chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); is_true = !!(pattern_data & (1 << (7 - ((chips->bitblt_running.bitblt.destination_addr + chips->bitblt_running.x) & 7)))); @@ -937,32 +1250,30 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; } else { + uint32_t pattern_pixel_addr = 0; if (chips->bitblt_running.bytes_per_pixel == 1) { - pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) - + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); + pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr + + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7); + + pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; } if (chips->bitblt_running.bytes_per_pixel == 2) { - pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)); - pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; + pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 1) & chips->svga.vram_mask] << 8; } if (chips->bitblt_running.bytes_per_pixel == 3) { - pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); + pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)); - pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; - - pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr - + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; + pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; + pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 1) & chips->svga.vram_mask] << 8; + pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 2) & chips->svga.vram_mask] << 16; } } if (chips->bitblt_running.bytes_per_pixel == 2) { @@ -980,7 +1291,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) : chips->bitblt_running.bitblt.pattern_source_key_bg; color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -1018,7 +1329,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -1030,20 +1341,21 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; + //chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); break; } case 2: /* 16 bits-per-pixel. */ { - chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); - chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; + chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] = (dest_pixel >> 8) & 0xFF; break; } case 3: /* 24 bits-per-pixel. */ { - chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); - chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); - chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips); + chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; + chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] = (dest_pixel >> 8) & 0xFF; + chips->svga.vram[(dest_addr + 2) & chips->svga.vram_mask] = (dest_pixel >> 16) & 0xFF; break; } } @@ -1211,7 +1523,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; while (orig_count_y == chips->bitblt_running.count_y) { int i = 0; - uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); + //uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); + uint8_t data = chips->svga.vram[orig_source_addr & chips->svga.vram_mask]; orig_source_addr++; for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(data & (1 << (7 - i)))); @@ -1230,14 +1543,15 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 1: /* Bit-aligned */ case 2: /* Byte-aligned */ { - uint32_t data = chips_69000_readb_linear(source_addr, chips); + //uint32_t data = chips_69000_readb_linear(source_addr, chips); + uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask]; chips_69000_bitblt_write(chips, data & 0xFF); source_addr += 1; break; } case 3: /* Word-aligned*/ { - uint32_t data = chips_69000_readw_linear(source_addr, chips); + uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); source_addr += 2; @@ -1245,7 +1559,8 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } case 4: /* Doubleword-aligned*/ { - uint32_t data = chips_69000_readl_linear(source_addr, chips); + uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8) + | (chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16) | (chips->svga.vram[(source_addr + 3) & chips->svga.vram_mask] << 24); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); @@ -1255,7 +1570,15 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } case 5: /* Quadword-aligned*/ { - uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); + uint64_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] + | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8) + | (chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16) + | (chips->svga.vram[(source_addr + 3) & chips->svga.vram_mask] << 24) + | ((uint64_t)chips->svga.vram[(source_addr + 4) & chips->svga.vram_mask] << 32ULL) + | ((uint64_t)chips->svga.vram[(source_addr + 5) & chips->svga.vram_mask] << 40ULL) + | ((uint64_t)chips->svga.vram[(source_addr + 6) & chips->svga.vram_mask] << 48ULL) + | ((uint64_t)chips->svga.vram[(source_addr + 7) & chips->svga.vram_mask] << 56ULL); + //uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); @@ -1280,20 +1603,21 @@ chips_69000_setup_bitblt(chips_69000_t* chips) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - pixel = chips_69000_readb_linear(source_addr, chips); + //pixel = chips_69000_readb_linear(source_addr, chips); + pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; break; } case 2: /* 16 bits-per-pixel. */ { - pixel = chips_69000_readb_linear(source_addr, chips); - pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; + pixel |= chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8; break; } case 3: /* 24 bits-per-pixel. */ { - pixel = chips_69000_readb_linear(source_addr, chips); - pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; - pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16; + pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; + pixel |= chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8; + pixel |= chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16; break; } } From 35125e70205ab59ed731059f67827dc472987eb5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 16 Mar 2025 15:24:24 +0600 Subject: [PATCH 029/158] Don't use starblit/endblit for renderer switches --- src/qt/qt_mainwindow.cpp | 4 ++-- src/qt/qt_rendererstack.cpp | 11 ++++++----- src/qt/qt_rendererstack.hpp | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 497b791ca..fb265f34d 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -2025,8 +2025,8 @@ MainWindow::on_actionRenderer_options_triggered() ui->stackedWidget->switchRenderer(static_cast(vid_api)); if (show_second_monitors) { for (int i = 1; i < MONITORS_NUM; i++) { - if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) { - ui->stackedWidget->switchRenderer(static_cast(vid_api)); + if (renderers[i]) { + renderers[i]->switchRenderer(static_cast(vid_api)); } } } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index bd1fd2609..2b1cfdf26 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -288,7 +288,8 @@ RendererStack::leaveEvent(QEvent *event) void RendererStack::switchRenderer(Renderer renderer) { - startblit(); + //startblit(); + switchInProgress = true; if (current) { rendererWindow->finalize(); removeWidget(current.get()); @@ -349,7 +350,7 @@ RendererStack::createRenderer(Renderer renderer) connect(hw, &OpenGLRenderer::initialized, [=]() { /* Buffers are available only after initialization. */ imagebufs = rendererWindow->getBuffers(); - endblit(); + switchInProgress = false; emit rendererChanged(); }); connect(hw, &OpenGLRenderer::errorInitializing, [=]() { @@ -381,7 +382,7 @@ RendererStack::createRenderer(Renderer renderer) connect(hw, &VulkanWindowRenderer::rendererInitialized, [=]() { /* Buffers are available only after initialization. */ imagebufs = rendererWindow->getBuffers(); - endblit(); + switchInProgress = false; emit rendererChanged(); }); connect(hw, &VulkanWindowRenderer::errorInitializing, [=]() { @@ -413,7 +414,7 @@ RendererStack::createRenderer(Renderer renderer) if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) { imagebufs = rendererWindow->getBuffers(); - endblit(); + switchInProgress = false; emit rendererChanged(); } } @@ -423,7 +424,7 @@ void RendererStack::blit(int x, int y, int w, int h) { if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || - (w > 2048) || (h > 2048) || + (w > 2048) || (h > 2048) || (switchInProgress) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set()) { video_blit_complete_monitor(m_monitor_index); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 309cae7f5..54ea49bb9 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -113,6 +113,7 @@ private: std::unique_ptr current; std::atomic_bool rendererTakesScreenshots; + std::atomic_bool switchInProgress{false}; }; #endif // QT_RENDERERCONTAINER_HPP From c77cef6d80cdfc4c6b824ebcade534eee1bce2b7 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sun, 16 Mar 2025 16:55:29 +0500 Subject: [PATCH 030/158] Fix Qt menu roles for certain menu items --- src/qt/qt_mainwindow.cpp | 1 + src/qt/qt_mainwindow.ui | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 497b791ca..cfd6e08aa 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -181,6 +181,7 @@ MainWindow::MainWindow(QWidget *parent) main_window = this; ui->setupUi(this); status->setSoundGainAction(ui->actionSound_gain); + ui->menuEGA_S_VGA_settings->menuAction()->setMenuRole(QAction::NoRole); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); #ifdef Q_OS_WINDOWS diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index b1dc0ecf1..ef3cf16c6 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -353,6 +353,9 @@ Exit + + QAction::QuitRole + @@ -815,6 +818,9 @@ Renderer options... + + QAction::NoRole + From 271a125301342b588456dd026ea90ae809105029 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 16 Mar 2025 23:33:40 +0600 Subject: [PATCH 031/158] Use `fpclassify` for FXAM instead of manual comparison NaN detection for interpreter floating point compare on ARM64 --- src/cpu/x87_ops.h | 14 ++++++++++++-- src/cpu/x87_ops_misc.h | 22 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 97f5415b9..6a51a2c7f 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -420,11 +420,19 @@ x87_compare(double a, double b) * situations, eg comparison of infinity (Unreal) */ uint32_t result = 0; double ea = a, eb = b; + const uint64_t ia = 0x3fec1a6ff866a936ULL; + const uint64_t ib = 0x3fec1a6ff866a938ULL; + + /* Hack to make CHKCOP happy. */ + if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8)) + return FPU_SW_C3; if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) eb = ea; - if (ea == eb) + if ((isnan(a) || isnan(b))) + result |= FPU_SW_C3 | FPU_SW_C2 | FPU_SW_C0; + else if (ea == eb) result |= FPU_SW_C3; else if (ea < eb) result |= FPU_SW_C0; @@ -473,7 +481,9 @@ x87_ucompare(double a, double b) * situations, eg comparison of infinity (Unreal) */ uint32_t result = 0; - if (a == b) + if ((isnan(a) || isnan(b))) + result |= FPU_SW_C3 | FPU_SW_C2 | FPU_SW_C0; + else if (a == b) result |= FPU_SW_C3; else if (a < b) result |= FPU_SW_C0; diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 5821a5cd5..4009eadd6 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -585,10 +585,24 @@ opFXAM(UNUSED(uint32_t fetchdat)) if (cpu_state.tag[cpu_state.TOP & 7] == 3) cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3); #endif - else if (ST(0) == 0.0) - cpu_state.npxs |= FPU_SW_C3; - else - cpu_state.npxs |= FPU_SW_C2; + else switch (fpclassify(ST(0))) + { + case FP_SUBNORMAL: + cpu_state.npxs |= FPU_SW_C2 | FPU_SW_C3; + break; + case FP_NAN: + cpu_state.npxs |= FPU_SW_C0; + break; + case FP_INFINITE: + cpu_state.npxs |= FPU_SW_C0 | FPU_SW_C2; + break; + case FP_ZERO: + cpu_state.npxs |= FPU_SW_C3; + break; + case FP_NORMAL: + cpu_state.npxs |= FPU_SW_C2; + break; + } if (ST(0) < 0.0) cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); From 1c5d432d3cf4332066ec48c0e572e11e95636ddb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Mar 2025 18:37:32 +0100 Subject: [PATCH 032/158] Disable special segment selector pushing behavior on Pentium onwards, fixes MSVC builds of ReactOS. --- src/cpu/cpu.c | 79 +++++++++++++++++++++++++----------------------- src/cpu/cpu.h | 1 + src/cpu/x86seg.c | 23 +++++++++----- 3 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index c4d084947..b821bc657 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -209,6 +209,7 @@ int is286; int is386; int is6117; int is486 = 1; +int is586 = 0; int cpu_isintel; int cpu_iscyrix; int hascache; @@ -552,6 +553,8 @@ cpu_set(void) cpu_16bitbus = (cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) || (cpu_s->cpu_type == CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC); cpu_64bitbus = (cpu_s->cpu_type >= CPU_WINCHIP); + is586 = cpu_64bitbus || (cpu_s->cpu_type == CPU_P24T); + if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; else @@ -4303,47 +4306,47 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) static uint8_t cpu_read(uint16_t addr, UNUSED(void *priv)) { + uint8_t ret = 0xff; + if (addr == 0xf007) - return 0x7f; + ret = 0x7f; + else if ((addr < 0xf0) && (addr & 1)) switch (cyrix_addr) { + case 0xc0: + ret = ccr0; + break; + case 0xc1: + ret = ccr1; + break; + case 0xc2: + ret = ccr2; + break; + case 0xc3: + ret = ccr3; + break; + case 0xe8: + ret = ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; + break; + case 0xe9: + ret = ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; + break; + case 0xea: + ret = ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; + break; + case 0xeb: + ret = ccr7; + break; + case 0xfe: + ret = cpu_s->cyrix_id & 0xff; + break; + case 0xff: + ret = cpu_s->cyrix_id >> 8; + break; - if (addr >= 0xf0) - return 0xff; /* FPU stuff */ - - if (addr & 1) { - switch (cyrix_addr) { - case 0xc0: - return ccr0; - case 0xc1: - return ccr1; - case 0xc2: - return ccr2; - case 0xc3: - return ccr3; - case 0xe8: - return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; - case 0xe9: - return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; - case 0xea: - return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; - case 0xeb: - return ccr7; - case 0xfe: - return cpu_s->cyrix_id & 0xff; - case 0xff: - return cpu_s->cyrix_id >> 8; - - default: - break; - } - - if ((cyrix_addr & 0xf0) == 0xc0) - return 0xff; - - if (cyrix_addr == 0x20 && (cpu_s->cpu_type == CPU_Cx5x86)) - return 0xff; + default: + break; } - - return 0xff; + + return ret; } void diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 8324c543e..d58da6998 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -513,6 +513,7 @@ extern int is286; extern int is386; extern int is6117; extern int is486; +extern int is586; extern int is_am486; extern int is_am486dxl; extern int is_pentium; diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 61c0edd9f..cd393812d 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -1113,7 +1113,7 @@ loadcscall(uint16_t seg) x86seg_log("Type %04X\n", type); if (type == 0x0c00) { - PUSHL_SEL(oldss); + is586 ? PUSHL(oldss) : PUSHL_SEL(oldss); PUSHL(oldsp2); if (cpu_state.abrt) { SS = oldss; @@ -1678,10 +1678,17 @@ pmodeint(int num, int soft) cpl_override = 1; if (type >= 0x0800) { if (cpu_state.eflags & VM_FLAG) { - PUSHL_SEL(GS); - PUSHL_SEL(FS); - PUSHL_SEL(DS); - PUSHL_SEL(ES); + if (is586) { + PUSHL(GS); + PUSHL(FS); + PUSHL(DS); + PUSHL(ES); + } else { + PUSHL_SEL(GS); + PUSHL_SEL(FS); + PUSHL_SEL(DS); + PUSHL_SEL(ES); + } if (cpu_state.abrt) return; op_loadseg(0, &cpu_state.seg_ds); @@ -1689,10 +1696,10 @@ pmodeint(int num, int soft) op_loadseg(0, &cpu_state.seg_fs); op_loadseg(0, &cpu_state.seg_gs); } - PUSHL_SEL(oldss); + is586 ? PUSHL(oldss) : PUSHL_SEL(oldss); PUSHL(oldsp); PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL_SEL(CS); + is586 ? PUSHL(CS) : PUSHL_SEL(CS); PUSHL(cpu_state.pc); if (cpu_state.abrt) return; @@ -1728,7 +1735,7 @@ pmodeint(int num, int soft) } if (type > 0x0800) { PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL_SEL(CS); + is586 ? PUSHL(CS) : PUSHL_SEL(CS); PUSHL(cpu_state.pc); if (cpu_state.abrt) return; From 9f200fe2e83c99c0e4b8076afe451bf0c3da8f98 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Mar 2025 21:20:15 +0100 Subject: [PATCH 033/158] 386 Interpreter: Check for debug breakpoint before segment limit and presence checking. --- src/cpu/386.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index caa5f84a2..c9a62fa6e 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -264,11 +264,7 @@ exec386_2386(int32_t cycs) ol = opcode_length[fetchdat & 0xff]; if ((ol == 3) && opcode_has_modrm[fetchdat & 0xff] && (((fetchdat >> 14) & 0x03) == 0x03)) ol = 2; - if (cpu_16bitbus) { - CHECK_READ_CS(MIN(ol, 2)); - } else { - CHECK_READ_CS(MIN(ol, 4)); - } + if (is386) ins_fetch_fault = cpu_386_check_instruction_fault(); @@ -276,6 +272,10 @@ exec386_2386(int32_t cycs) if (ins_fetch_fault) { ins_fetch_fault = 0; cpu_state.abrt = 1; + } else if (cpu_16bitbus) { + CHECK_READ_CS(MIN(ol, 2)); + } else { + CHECK_READ_CS(MIN(ol, 4)); } if (!cpu_state.abrt) { From 52a16529dcfd554c6e7e7a2c5c921388ee9bb9a4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 16 Mar 2025 23:54:55 +0100 Subject: [PATCH 034/158] 386 Interpreter: Fix execute breakpoints. --- src/cpu/386.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index c9a62fa6e..6abb7da18 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -269,9 +269,11 @@ exec386_2386(int32_t cycs) ins_fetch_fault = cpu_386_check_instruction_fault(); /* Breakpoint fault has priority over other faults. */ - if (ins_fetch_fault) { + if ((cpu_state.abrt == 0) & ins_fetch_fault) { + x86gen(); ins_fetch_fault = 0; - cpu_state.abrt = 1; + /* No instructions executed at this point. */ + goto block_ended; } else if (cpu_16bitbus) { CHECK_READ_CS(MIN(ol, 2)); } else { @@ -288,7 +290,6 @@ exec386_2386(int32_t cycs) trap |= !!(cpu_state.flags & T_FLAG); cpu_state.pc++; - cpu_state.eflags &= ~(RF_FLAG); if (opcode == 0xf0) in_lock = 1; x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); @@ -316,6 +317,7 @@ exec386_2386(int32_t cycs) if (cpu_end_block_after_ins) cpu_end_block_after_ins--; +block_ended: if (cpu_state.abrt) { flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; @@ -338,6 +340,9 @@ exec386_2386(int32_t cycs) #endif } } + + if (!x86_was_reset && ins_fetch_fault) + x86gen(); } else if (new_ne) { flags_rebuild(); new_ne = 0; From dd4e493f646e316162c732b70ad86a3b81cc3b0f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 00:07:41 +0100 Subject: [PATCH 035/158] Applied the fix to the optional 486 implementation as well. --- src/cpu/386.c | 2 +- src/cpu/386_dynarec.c | 45 ++++++++++++++++++------------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/cpu/386.c b/src/cpu/386.c index 6abb7da18..ed4b40ab2 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -341,7 +341,7 @@ block_ended: } } - if (!x86_was_reset && ins_fetch_fault) + if (is386 && !x86_was_reset && ins_fetch_fault) x86gen(); } else if (new_ne) { flags_rebuild(); diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 5f41c416a..fd6285057 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -276,11 +276,7 @@ exec386_dynarec_int(void) cpu_block_end = 0; x86_was_reset = 0; -# ifdef USE_DEBUG_REGS_486 - if (trap & 2) { -# else if (trap == 2) { -# endif /* Handle the T bit in the new TSS first. */ CPU_BLOCK_END(); goto block_ended; @@ -297,13 +293,6 @@ exec386_dynarec_int(void) cpu_state.ea_seg = &cpu_state.seg_ds; cpu_state.ssegs = 0; -# ifdef USE_DEBUG_REGS_486 - if (UNLIKELY(cpu_386_check_instruction_fault())) { - x86gen(); - goto block_ended; - } -# endif - fetchdat = fastreadl_fetch(cs + cpu_state.pc); # ifdef ENABLE_386_DYNAREC_LOG if (in_smm) @@ -370,13 +359,7 @@ exec386_dynarec_int(void) block_ended: if (!cpu_state.abrt && !new_ne && trap) { -# ifdef USE_DEBUG_REGS_486 - //pclog("Debug trap 0x%X\n", trap); - if (trap & 2) dr[6] |= 0x8000; - if (trap & 1) dr[6] |= 0x4000; -# else dr[6] |= (trap == 2) ? 0x8000 : 0x4000; -# endif trap = 0; # ifndef USE_NEW_DYNAREC @@ -902,6 +885,9 @@ exec386(int32_t cycs) cycdiff = 0; oldcyc = cycles; while (cycdiff < cycle_period) { +#ifdef USE_DEBUG_REGS_486 + int ins_fetch_fault = 0; +#endif ins_cycles = cycles; #ifndef USE_NEW_DYNAREC @@ -919,8 +905,14 @@ exec386(int32_t cycs) cpu_state.ssegs = 0; #ifdef USE_DEBUG_REGS_486 - if (UNLIKELY(cpu_386_check_instruction_fault())) { + if (is386) + ins_fetch_fault = cpu_386_check_instruction_fault(); + + /* Breakpoint fault has priority over other faults. */ + if ((cpu_state.abrt == 0) & ins_fetch_fault) { x86gen(); + ins_fetch_fault = 0; + /* No instructions executed at this point. */ goto block_ended; } #endif @@ -972,11 +964,13 @@ exec386(int32_t cycs) block_ended: #endif if (cpu_state.abrt) { + uint8_t oop = opcode; flags_rebuild(); tempi = cpu_state.abrt & ABRT_MASK; cpu_state.abrt = 0; x86_doabrt(tempi); if (cpu_state.abrt) { + pclog("Double fault - %02X\n", oop); cpu_state.abrt = 0; #ifndef USE_NEW_DYNAREC CS = oldcs; @@ -993,6 +987,11 @@ block_ended: #endif } } + +#ifdef USE_DEBUG_REGS_486 + if (is386 && !x86_was_reset && ins_fetch_fault) + x86gen(); +#endif } else if (new_ne) { flags_rebuild(); @@ -1005,20 +1004,14 @@ block_ended: } else if (trap) { flags_rebuild(); #ifdef USE_DEBUG_REGS_486 - if (trap & 1) - dr[6] |= 0x4000; - if (trap & 2) - dr[6] |= 0x8000; + if (trap & 2) dr[6] |= 0x8000; + if (trap & 1) dr[6] |= 0x4000; #endif - trap = 0; #ifndef USE_NEW_DYNAREC oldcs = CS; #endif cpu_state.oldpc = cpu_state.pc; -#ifndef USE_DEBUG_REGS_486 - dr[6] |= 0x4000; -#endif x86_int(1); } From bb1b6660103b9b61cf1d7621a0aa75cae09c0721 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 00:43:18 +0100 Subject: [PATCH 036/158] Removed some commented out stuff. --- src/cdrom/cdrom.c | 8 +----- src/disk/hdc_ide.c | 61 ++----------------------------------------- src/scsi/scsi_cdrom.c | 16 ------------ 3 files changed, 3 insertions(+), 82 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 6805d42c6..b30d93812 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1796,11 +1796,8 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) position), the rest are stuff like ISRC etc., which can be all zeroes. */ case 0x00: - if (dev->bus_type == CDROM_BUS_ATAPI) { - // pclog("Format 0 on ATAPI\n"); + if (dev->bus_type == CDROM_BUS_ATAPI) break; - } - // pclog("Format 0 on SCSI\n"); diff = 0; fallthrough; case 0x01: @@ -1847,9 +1844,6 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, const int msf) b[10] = (dat >> 8) & 0xff; b[11] = dat & 0xff; } - // pclog("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - // b[ 0], b[ 1], b[ 2], b[ 3], b[ 4], b[ 5], b[ 6], b[ 7], - // b[ 8], b[ 9], b[10], b[11]); if (b[0] != 0x00) break; base += 12; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index eb160c41b..61211228a 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1091,7 +1091,6 @@ ide_atapi_callback(ide_t *ide) ide_irq_raise(ide); break; case PHASE_DATA_IN_DMA: - // pclog("Reading block %i (%i, %i)... ", ide->sc->sector_len + 1, ide->sc->block_len, ide->sc->packet_len); if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { if (ide->sc->block_len == 0) { @@ -1119,16 +1118,13 @@ ide_atapi_callback(ide_t *ide) default: break; case 0: - // pclog("ERROR\n"); if (ide->bus_master_error) ide->bus_master_error(ide->sc); break; case 2: - // pclog("WAIT\n"); ide_atapi_command_bus(ide); break; case 3: - // pclog("DONE\n"); /* Reached EOT - terminate the command as there's nothing more to transfer. */ ide->sc->packet_status = PHASE_COMPLETE; @@ -1138,7 +1134,6 @@ ide_atapi_callback(ide_t *ide) ide->command_stop(ide->sc); fallthrough; case 1: - // pclog("NEXT\n"); if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) ide_atapi_callback(ide); @@ -1214,7 +1209,6 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide->tf->pos = dev->request_pos = 0; if (dev->block_len == 0) { - // pclog("ide_atapi_pio_request(): Processing instant command...\n"); if (out && (ide->phase_data_out != NULL)) ide->phase_data_out(dev); else if (!out && (ide->command_stop != NULL)) @@ -1254,21 +1248,10 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) if (dev->block_len != 0) { if (out) { - if (ide->write != NULL) { -#if 0 - pclog("ide_atapi_pio_request(): Continuing write command " - "(dev->sector_len = %i)...\n", dev->sector_len); -#endif - + if (ide->write != NULL) ide->write(dev); - } if (dev->sector_len == 0) { -#if 0 - pclog("ide_atapi_pio_request(): Ending write command " - "(dev->sector_len = %i)...\n", dev->sector_len); -#endif - ide->sc->packet_status = PHASE_COMPLETE; ide->sc->callback = 0.0; @@ -1279,11 +1262,6 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) } } else { if (dev->sector_len == 0) { -#if 0 - pclog("ide_atapi_pio_request(): Ending read command " - "(dev->sector_len = %i)...\n", dev->sector_len); -#endif - if (ide->command_stop != NULL) ide->command_stop(dev); @@ -1291,14 +1269,8 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide->sc->callback = 0.0; ide_atapi_callback(ide); - } else if (ide->read != NULL) { -#if 0 - pclog("ide_atapi_pio_request(): Continuing read command " - "(dev->sector_len = %i)...\n", dev->sector_len); -#endif - + } else if (ide->read != NULL) ide->read(dev); - } } } } @@ -1332,26 +1304,6 @@ ide_atapi_packet_read(ide_t *ide) /* Time for a DRQ. */ ide_atapi_pio_request(ide, 0); } -#if 0 - else if ((dev->block_len != 0) && - (dev->sector_len != 0) && - ((dev->request_pos % dev->block_len) == 0)) { - if (dev->sector_len == 0) { - // pclog("ide_atapi_packet_read(): Ending read command (dev->sector_len = %i)...\n", dev->sector_len); - - if (ide->command_stop != NULL) - ide->command_stop(ide->sc); - - ide->sc->packet_status = PHASE_COMPLETE; - ide->sc->callback = 0.0; - - ide_atapi_callback(ide); - } else if (ide->read != NULL) { - // pclog("ide_atapi_packet_read(): Continuing read command (dev->sector_len = %i)...\n", dev->sector_len); - ide->read(dev); - } - } -#endif } return ret; @@ -1386,15 +1338,6 @@ ide_atapi_packet_write(ide_t *ide, const uint16_t val) /* Time for a DRQ. */ ide_atapi_pio_request(ide, 1); } -#if 0 - else if ((dev->block_len != 0) && - ((dev->request_pos % dev->block_len) == 0) && - (ide->write != NULL)) { - // pclog("ide_atapi_packet_write(): Continuing write command (dev->sector_len = %i)...\n", dev->sector_len); - - ide->write(dev); - } -#endif } else if (dev->packet_status == PHASE_IDLE) { if (ide->tf->pos >= 12) { ide->tf->pos = 0; diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index eed57c63b..292c54127 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -663,8 +663,6 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) static void scsi_cdrom_set_period(scsi_cdrom_t *dev) { - // const uint8_t cmd = dev->current_cdb[0]; - scsi_cdrom_log(dev->log, "Current speed: %ix\n", dev->drv->cur_speed); dev->callback = 0; @@ -689,7 +687,6 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) /* 44100 * 16 bits * 2 channels = 176400 bytes per second */ bytes_per_second = 176400.0; bytes_per_second *= (double) dev->drv->cur_speed; - // pclog("Current speed: %ix\n", dev->drv->cur_speed); } else { bytes_per_second = scsi_cdrom_bus_speed(dev); if (bytes_per_second == 0.0) { @@ -711,7 +708,6 @@ scsi_cdrom_set_period(scsi_cdrom_t *dev) (dev->packet_len / dev->block_len)); period *= ((double) num) * 2352.0; - // pclog("[%02X] Calculated period for %i * 2352 bytes\n", cmd, num); } scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n", (uint64_t) period); @@ -1082,7 +1078,6 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int dev->sector_len--; - // pclog("Sector read to buffer position %08X\n", dev->buffer_pos); dev->buffer_pos += temp_len; } } @@ -2470,7 +2465,6 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_REZERO_UNIT: - // pclog("Rezero unit\n"); dev->was_cached = 0; scsi_cdrom_stop(sc); dev->requested_blocks = 0; @@ -2505,7 +2499,6 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_SCAN_PIONEER: case GPCMD_AUDIO_SCAN: - // pclog("Audio scan\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->was_cached = 0; @@ -2552,7 +2545,6 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) scsi_cdrom_buf_alloc(dev, 65536); toc_format = cdb[2] & 0xf; - // pclog("READ TOC format %1X\n", toc_format); if (toc_format == 0) toc_format = (cdb[9] >> 6) & 3; @@ -3170,20 +3162,16 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; - // pclog("Play audio (10)\n"); break; case GPCMD_PLAY_AUDIO_12: msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - // pclog("Play audio (12)\n"); break; case GPCMD_PLAY_AUDIO_MSF: msf = 1; pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - // pclog("Play audio MSF: %2i:%02i.%02i-%2i:%02i.%02i\n", - // cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8]); break; case GPCMD_PLAY_AUDIO_TRACK_INDEX: msf = 2; @@ -3192,19 +3180,16 @@ scsi_cdrom_command(scsi_common_t *sc, const uint8_t *cdb) len = cdb[7]; } else ret = 0; - // pclog("Play audio track index\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10: msf = 0x100 | cdb[6]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[7] << 8) | cdb[8]; - // pclog("Play audio track relative (10)\n"); break; case GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12: msf = 0x100 | cdb[10]; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - // pclog("Play audio track relative (12)\n"); break; default: @@ -3505,7 +3490,6 @@ atapi_out: case GPCMD_SEEK_6: case GPCMD_SEEK_10: - // pclog("Seek\n"); scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->was_cached = 0; From 79134f3b21648d280f56303a2c43d92821565eb5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 03:40:52 +0100 Subject: [PATCH 037/158] Assorted Cyrix (and Codegen opcode Mod R/M passing table) fixes - fixes Windows 98 SE on Cyrix 6x86's with power management enabled. --- src/codegen/codegen_x86-64.c | 8 +++--- src/codegen/codegen_x86.c | 8 +++--- src/codegen_new/codegen.c | 8 +++--- src/cpu/386_common.c | 50 +++++++++++++++++++++++++++++++++++- src/cpu/x86.h | 6 +++++ src/cpu/x86_ops_cyrix.h | 11 ++++++-- src/cpu/x86_ops_rep.h | 2 ++ src/cpu/x86_ops_rep_2386.h | 2 ++ src/cpu/x86_ops_rep_dyn.h | 2 ++ src/cpu/x86seg.c | 10 +++----- src/io.c | 16 ++++++++++++ 11 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 04c2136ff..00db630a3 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -499,14 +499,14 @@ static int opcode_modrm[256] = { int opcode_0f_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index df0ed3bfd..935e2bab6 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1643,14 +1643,14 @@ static int opcode_modrm[256] = { int opcode_0f_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 39ab69b3d..82f6cd037 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -359,14 +359,14 @@ static uint8_t opcode_modrm[256] = { static uint8_t opcode_0f_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ - 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 8a2bb4ab8..5b0e1a5c4 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -107,6 +107,12 @@ uint32_t backupregs[16]; x86seg _oldds; +uint8_t rep_op = 0x00; +uint8_t is_smint = 0; + +uint16_t io_port = 0x0000; +uint32_t io_val = 0x00000000; + int opcode_has_modrm[256] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ @@ -1215,7 +1221,7 @@ smram_restore_state_amd_k(uint32_t *saved_state) } static void -smram_save_state_cyrix(uint32_t *saved_state, UNUSED(int in_hlt)) +smram_save_state_cyrix(uint32_t *saved_state, int in_hlt) { saved_state[0] = dr[7]; saved_state[1] = cpu_state.flags | (cpu_state.eflags << 16); @@ -1224,6 +1230,35 @@ smram_save_state_cyrix(uint32_t *saved_state, UNUSED(int in_hlt)) saved_state[4] = cpu_state.pc; saved_state[5] = CS | (CPL << 21); saved_state[6] = 0x00000000; + saved_state[7] = 0x00010000; + + if (((opcode >= 0x6e) && (opcode <= 0x6f)) || ((opcode >= 0xe6) && (opcode <= 0xe7)) || + ((opcode >= 0xee) && (opcode <= 0xef))) { + saved_state[6] |= 0x00000002; + saved_state[7] = (opcode & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000; + } else if (((opcode == 0xf2) || (opcode == 0xf3)) && (rep_op >= 0x6e) && (rep_op <= 0x6f)) { + saved_state[6] |= 0x00000006; + saved_state[7] = (rep_op & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000; + } else if (((opcode == 0xf2) || (opcode == 0xf3)) && (rep_op >= 0x6e) && (rep_op <= 0x6f)) { + saved_state[6] |= 0x00000004; + saved_state[7] = (rep_op & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000; + } + + if (is_smint) { + saved_state[6] |= 0x00000008; + is_smint = 0; + } + + if (in_hlt) + saved_state[6] |= 0x00000010; + + saved_state[7] |= io_port; + saved_state[8] = io_val; + + if (saved_state[6] & 0x00000002) + saved_state[9] = ESI; + else + saved_state[9] = EDI; } static void @@ -1234,6 +1269,13 @@ smram_restore_state_cyrix(uint32_t *saved_state) cpu_state.eflags = saved_state[1] >> 16; cr0 = saved_state[2]; cpu_state.pc = saved_state[4]; + /* Restore CPL. */ + cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x9f) | (((saved_state[5] >> 21) & 0x03) << 5); + + if (saved_state[6] & 0x00000002) + ESI = saved_state[9]; + else + EDI = saved_state[9]; } void @@ -1368,6 +1410,9 @@ enter_smm(int in_hlt) writememl(0, smram_state - 0x14, saved_state[4]); writememl(0, smram_state - 0x18, saved_state[5]); writememl(0, smram_state - 0x24, saved_state[6]); + writememl(0, smram_state - 0x28, saved_state[7]); + writememl(0, smram_state - 0x2c, saved_state[8]); + writememl(0, smram_state - 0x30, saved_state[9]); } else { for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { smram_state -= 4; @@ -1452,6 +1497,9 @@ leave_smm(void) else cyrix_load_seg_descriptor_2386(smram_state - 0x20, &cpu_state.seg_cs); saved_state[6] = readmeml(0, smram_state - 0x24); + saved_state[7] = readmeml(0, smram_state - 0x28); + saved_state[8] = readmeml(0, smram_state - 0x2c); + saved_state[9] = readmeml(0, smram_state - 0x30); } else { for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) { smram_state -= 4; diff --git a/src/cpu/x86.h b/src/cpu/x86.h index 327af8964..ccfeadea0 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -103,4 +103,10 @@ extern int fpu_cycles; extern void x86illegal(void); +extern uint8_t rep_op; +extern uint8_t is_smint; + +extern uint16_t io_port; +extern uint32_t io_val; + #endif /*EMU_X86_H*/ diff --git a/src/cpu/x86_ops_cyrix.h b/src/cpu/x86_ops_cyrix.h index 8c3d6e155..ac864cd20 100644 --- a/src/cpu/x86_ops_cyrix.h +++ b/src/cpu/x86_ops_cyrix.h @@ -63,18 +63,23 @@ opRSDC_common(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*ES*/ cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es); + ES = readmemw(0, easeg + cpu_state.eaaddr + 8); break; case 0x18: /*DS*/ cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds); + DS = readmemw(0, easeg + cpu_state.eaaddr + 8); break; case 0x10: /*SS*/ cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss); + SS = readmemw(0, easeg + cpu_state.eaaddr + 8); break; case 0x20: /*FS*/ cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs); + FS = readmemw(0, easeg + cpu_state.eaaddr + 8); break; case 0x28: /*GS*/ cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs); + GS = readmemw(0, easeg + cpu_state.eaaddr + 8); break; default: x86illegal(); @@ -216,8 +221,10 @@ opSMINT(UNUSED(uint32_t fetchdat)) { if (in_smm) fatal("opSMINT\n"); - else - x86illegal(); + else { + is_smint = 1; + enter_smm(0); + } return 1; } diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index c75684d31..6449912e9 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -855,6 +855,7 @@ opREPNE(uint32_t fetchdat) CLOCK_CYCLES(2); PREFETCH_PREFIX(); + rep_op = fetchdat & 0xff; if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); @@ -869,6 +870,7 @@ opREPE(uint32_t fetchdat) CLOCK_CYCLES(2); PREFETCH_PREFIX(); + rep_op = fetchdat & 0xff; if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); diff --git a/src/cpu/x86_ops_rep_2386.h b/src/cpu/x86_ops_rep_2386.h index aa1984f81..3b96d54e3 100644 --- a/src/cpu/x86_ops_rep_2386.h +++ b/src/cpu/x86_ops_rep_2386.h @@ -843,6 +843,7 @@ opREPNE(uint32_t fetchdat) CLOCK_CYCLES(2); PREFETCH_PREFIX(); + rep_op = fetchdat & 0xff; if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); @@ -857,6 +858,7 @@ opREPE(uint32_t fetchdat) CLOCK_CYCLES(2); PREFETCH_PREFIX(); + rep_op = fetchdat & 0xff; if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); diff --git a/src/cpu/x86_ops_rep_dyn.h b/src/cpu/x86_ops_rep_dyn.h index bdb721ab0..1220c0da3 100644 --- a/src/cpu/x86_ops_rep_dyn.h +++ b/src/cpu/x86_ops_rep_dyn.h @@ -761,6 +761,7 @@ opREPNE(uint32_t fetchdat) cpu_state.pc++; CLOCK_CYCLES(2); + rep_op = fetchdat & 0xff; if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); @@ -774,6 +775,7 @@ opREPE(uint32_t fetchdat) cpu_state.pc++; CLOCK_CYCLES(2); + rep_op = fetchdat & 0xff; if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index cd393812d..2a0601661 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -2581,19 +2581,17 @@ cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg) cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; else cpu_cur_status |= CPU_STATUS_NOTFLATDS; -#ifdef USE_DYNAREC - codegen_flat_ds = 0; -#endif } + + if (seg == &cpu_state.seg_cs) + set_use32(segdat[3] & 0x40); + if (seg == &cpu_state.seg_ss) { if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; else cpu_cur_status |= CPU_STATUS_NOTFLATSS; set_stack32((segdat[3] & 0x40) ? 1 : 0); -#ifdef USE_DYNAREC - codegen_flat_ss = 0; -#endif } } } diff --git a/src/io.c b/src/io.c index 27f8503b0..9554c971d 100644 --- a/src/io.c +++ b/src/io.c @@ -28,6 +28,7 @@ #include <86box/io.h> #include <86box/timer.h> #include "cpu.h" +#include "x86.h" #include <86box/m_amstrad.h> #include <86box/pci.h> @@ -344,6 +345,8 @@ inb(uint16_t port) int qfound = 0; #endif + io_port = port; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif @@ -408,6 +411,9 @@ outb(uint16_t port, uint8_t val) int qfound = 0; #endif + io_port = port; + io_val = val; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif @@ -464,6 +470,8 @@ inw(uint16_t port) #endif uint8_t ret8[2]; + io_port = port; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif @@ -540,6 +548,9 @@ outw(uint16_t port, uint16_t val) int qfound = 0; #endif + io_port = port; + io_val = val; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif @@ -612,6 +623,8 @@ inl(uint16_t port) int qfound = 0; #endif + io_port = port; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif @@ -720,6 +733,9 @@ outl(uint16_t port, uint32_t val) #endif int i = 0; + io_port = port; + io_val = val; + #ifdef USE_DEBUG_REGS_486 io_debug_check_addr(port); #endif From 49463607c1b5825d7805fdc5abcdec9bb1ed4027 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 04:29:58 +0100 Subject: [PATCH 038/158] C&T 69000: Rewrite the PCI register handling and intialize the registers to sane default, fixes the card's detection by the Windows 98 driver installer. --- src/video/vid_chips_69000.c | 248 +++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 104 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index b0e8db35a..c17fe2004 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -107,6 +107,7 @@ typedef struct chips_69000_t { uint8_t mm_regs[256], mm_index; uint8_t flat_panel_regs[256], flat_panel_index; uint8_t ext_regs[256], ext_index; + uint8_t pci_regs[256]; union { uint32_t mem_regs[4]; @@ -2156,57 +2157,74 @@ static uint8_t chips_69000_pci_read(UNUSED(int func), int addr, void *priv) { chips_69000_t *chips = (chips_69000_t *) priv; + uint8_t ret = 0x00; - { - switch (addr) { - case 0x00: - return 0x2C; - case 0x01: - return 0x10; - case 0x02: - return 0xC0; - case 0x03: - return 0x00; - case 0x04: - return (chips->pci_conf_status & 0b11100011) | 0x80; - case 0x06: - return 0x80; - case 0x07: - return 0x02; - case 0x08: - case 0x09: - case 0x0a: - return 0x00; - case 0x0b: - return 0x03; - case 0x13: - return chips->linear_mapping.base >> 24; - case 0x30: - return chips->pci_rom_enable & 0x1; - case 0x31: - return 0x0; - case 0x32: - return chips->rom_addr & 0xFF; - case 0x33: - return (chips->rom_addr & 0xFF00) >> 8; - case 0x3c: - return chips->pci_line_interrupt; - case 0x3d: - return 0x01; - case 0x2C: - case 0x2D: - case 0x6C: - case 0x6D: - return (chips->subsys_vid >> ((addr & 1) * 8)) & 0xFF; - case 0x2E: - case 0x2F: - case 0x6E: - case 0x6F: - return (chips->subsys_pid >> ((addr & 1) * 8)) & 0xFF; - default: - return 0x00; - } + switch (addr) { + case 0x00: + ret = 0x2c; + break; + case 0x01: + ret = 0x10; + break; + case 0x02: + ret = 0xc0; + break; + case 0x03: + ret = 0x00; + break; + + case 0x04: + ret = (chips->pci_conf_status & 0x73) | 0x80; + break; + case 0x05: + ret = chips->pci_regs[addr] & 0x01; + break; + case 0x06: + ret = 0x80; + break; + case 0x07: + ret = chips->pci_regs[addr] | 0x02; + break; + + case 0x0b: + ret = 0x03; + break; + + case 0x13: + ret = chips->linear_mapping.base >> 24; + break; + + case 0x2c ... 0x2d: + case 0x6c ... 0x6d: + ret = chips->subsys_vid_b[addr & 1]; + break; + case 0x2e ... 0x2f: + case 0x6e ... 0x6f: + ret = chips->subsys_pid_b[addr & 1]; + break; + + case 0x30: + ret = chips->pci_rom_enable & 0x1; + break; + case 0x32: + ret = chips->rom_addr & 0xff; + break; + case 0x33: + ret = (chips->rom_addr & 0xff00) >> 8; + break; + + case 0x3c: + ret = chips->pci_line_interrupt; + break; + case 0x3d: + ret = 0x01; + break; + + default: + break; } + + return ret; } static void @@ -2214,67 +2232,77 @@ chips_69000_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) { chips_69000_t *chips = (chips_69000_t *) priv; - { - switch (addr) { - case 0x04: - { - chips->pci_conf_status = val; - io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); - mem_mapping_disable(&chips->linear_mapping); - mem_mapping_disable(&chips->svga.mapping); - if (chips->pci_conf_status & PCI_COMMAND_IO) { - io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); - } - if (chips->pci_conf_status & PCI_COMMAND_MEM) { - mem_mapping_enable(&chips->svga.mapping); - if (chips->linear_mapping.base) - mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); - } - break; - } - case 0x13: - { - chips->linear_mapping.base = val << 24; - if (chips->linear_mapping.base) - mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); - break; - } - case 0x3c: - chips->pci_line_interrupt = val; - break; - case 0x30: - if (chips->on_board) break; + switch (addr) { + case 0x04: + chips->pci_conf_status = val; + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (!chips->on_board) + mem_mapping_disable(&chips->bios_rom.mapping); + if (val & PCI_COMMAND_IO) + io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + if (val & PCI_COMMAND_MEM) { + if (!chips->on_board && (chips->pci_rom_enable & 1)) + mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); + mem_mapping_enable(&chips->svga.mapping); + if (chips->linear_mapping.base > 0x00000000) + mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); + } + break; + case 0x05: + chips->pci_regs[addr] = val & 0x01; + break; + case 0x07: + chips->pci_regs[addr] &= ~(val & 0xc8); + break; + + case 0x13: + chips->linear_mapping.base = val << 24; + mem_mapping_disable(&chips->linear_mapping); + if ((chips->pci_conf_status & PCI_COMMAND_MEM) && + (chips->linear_mapping.base > 0x00000000)) + mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); + break; + + case 0x30: + if (!chips->on_board) { chips->pci_rom_enable = val & 0x1; mem_mapping_disable(&chips->bios_rom.mapping); - if (chips->pci_rom_enable & 1) { + if ((chips->pci_conf_status & PCI_COMMAND_MEM) && + (chips->pci_rom_enable & 1)) mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); - } - break; - case 0x32: - if (chips->on_board) break; - chips->rom_addr &= ~0xFF; - chips->rom_addr |= val & 0xFC; - if (chips->pci_rom_enable & 1) { + } + break; + case 0x32: + if (!chips->on_board) { + chips->rom_addr &= ~0xff; + chips->rom_addr |= val & 0xfc; + if ((chips->pci_conf_status & PCI_COMMAND_MEM) && + (chips->pci_rom_enable & 1)) mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); - } - break; - case 0x33: - if (chips->on_board) break; - chips->rom_addr &= ~0xFF00; + } + break; + case 0x33: + if (!chips->on_board) { + chips->rom_addr &= ~0xff00; chips->rom_addr |= (val << 8); - if (chips->pci_rom_enable & 1) { + if ((chips->pci_conf_status & PCI_COMMAND_MEM) && + (chips->pci_rom_enable & 1)) mem_mapping_set_addr(&chips->bios_rom.mapping, chips->rom_addr << 16, 0x10000); - } - break; - case 0x6C: - case 0x6D: - chips->subsys_vid_b[addr & 1] = val; - break; - case 0x6E: - case 0x6F: - chips->subsys_pid_b[addr & 1] = val; - break; - } + } + break; + + case 0x3c: + chips->pci_line_interrupt = val; + break; + + case 0x6c ... 0x6d: + chips->subsys_vid_b[addr & 1] = val; + break; + case 0x6e ... 0x6f: + chips->subsys_pid_b[addr & 1] = val; + break; } } @@ -2839,6 +2867,18 @@ chips_69000_init(const device_t *info) chips->flat_panel_regs[0x01] = 1; + chips->pci_conf_status = 0x00; + chips->pci_rom_enable = 0x00; + chips->rom_addr = 0x0000; + chips->subsys_vid = 0x102c; + chips->subsys_pid = 0x00c0; + + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (!chips->on_board) + mem_mapping_disable(&chips->bios_rom.mapping); + *reset_state = *chips; return chips; From b1a77195abe7b513583010b383a7f9ae317a16d2 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 17 Mar 2025 21:23:32 +0600 Subject: [PATCH 039/158] C&T 69000: Fix bad refresh rate --- src/video/vid_chips_69000.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index c17fe2004..f7ed7ef14 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -1428,7 +1428,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bytes_skip = 0; chips->bitblt_running.mono_bytes_pitch = 0; chips->bitblt_running.mono_bits_skip_left = 0; - int orig_cycles = cycles; if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); @@ -1632,7 +1631,6 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); - cycles = orig_cycles; chips_69000_bitblt_interrupt(chips); } @@ -1644,7 +1642,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { - int orig_cycles = cycles; chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bitblt.monochrome_source_alignment == 1) { uint8_t val = chips->bitblt_running.bytes_port[0]; @@ -1662,7 +1659,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(chips->bitblt_running.bytes_port[j] & (1 << (7 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { - cycles = orig_cycles; return; } } @@ -1678,7 +1674,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); if (orig_count_y != chips->bitblt_running.count_y && chips->bitblt_running.bitblt.monochrome_source_alignment != 1) { - cycles = orig_cycles; return; } } @@ -1692,7 +1687,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 16; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (15 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { - cycles = orig_cycles; return; } } @@ -1706,7 +1700,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 32; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (31 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { - cycles = orig_cycles; return; } } @@ -1729,12 +1722,10 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 64; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (63 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { - cycles = orig_cycles; return; } } } - cycles = orig_cycles; return; } @@ -1744,7 +1735,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { - int orig_cycles = cycles; uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; if (chips->bitblt_running.bytes_per_pixel >= 2) @@ -1755,7 +1745,6 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; chips_69000_process_pixel(chips, source_pixel); - cycles = orig_cycles; chips->bitblt_running.x += chips->bitblt_running.x_dir; if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { @@ -2746,7 +2735,7 @@ chips_69000_getclock(int clock, void *priv) int pl = ((chips->ext_regs[0xcb] >> 4) & 7); float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); - if (chips->ext_regs[0xcb] & 4) + if (!(chips->ext_regs[0xcb] & 4)) fvco *= 4.0; float fo = fvco / (float)(1 << pl); @@ -2846,7 +2835,7 @@ chips_69000_init(const device_t *info) chips->svga.bpp = 8; chips->svga.miscout = 1; - chips->svga.vblank_start = chips_69000_vblank_start; + chips->svga.vsync_callback = chips_69000_vblank_start; chips->svga.getclock = chips_69000_getclock; chips->svga.conv_16to32 = chips_69000_conv_16to32; chips->svga.line_compare = chips_69000_line_compare; From 1bf78aebfdc599d65c67e6ff28ebbb9382a79f68 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 17 Mar 2025 21:45:50 +0600 Subject: [PATCH 040/158] C&T 69000: Adjust interrupt conditions --- src/video/vid_chips_69000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index f7ed7ef14..29521d1ae 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -240,7 +240,7 @@ chips_69000_write_flat_panel(chips_69000_t* chips, uint8_t val) void chips_69000_interrupt(chips_69000_t* chips) { - pci_irq(chips->slot, PCI_INTA, 0, !!((chips->mem_regs[0] & chips->mem_regs[1]) & 0x80004040), &chips->irq_state); + pci_irq(chips->slot, PCI_INTA, 0, !!(chips->mem_regs[0] & chips->mem_regs[1] & 0x80004040), &chips->irq_state); } void @@ -2416,7 +2416,7 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) { chips->mem_regs_b[addr & 0xF] = val; chips->mem_regs[(addr >> 2) & 0x3] &= 0x80004040; - if (addr == 0x605 || addr == 0x607) + if (addr == 0x601 || addr == 0x603) chips_69000_interrupt(chips); break; } From 277273c05da8153dfe59a9ec0a8656d36b1d5939 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 16:54:41 +0100 Subject: [PATCH 041/158] ATAPI PIO: Do not prematurely terminate the command if bytes are left to be transferred but all sectors have already been read into the buffer, fixes FreeBSD CD-ROM boot on some machines. --- src/disk/hdc_ide.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 61211228a..bf0d4d286 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1197,7 +1197,8 @@ ide_atapi_callback(ide_t *ide) static void ide_atapi_pio_request(ide_t *ide, uint8_t out) { - scsi_common_t *dev = ide->sc; + scsi_common_t *dev = ide->sc; + int left = 0; ide_irq_lower(ide); @@ -1221,6 +1222,8 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos, out ? "written" : "read", dev->packet_len - ide->tf->pos); + left = 1; + /* If less than (packet length) bytes are remaining, update packet length accordingly. @@ -1252,23 +1255,33 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide->write(dev); if (dev->sector_len == 0) { - ide->sc->packet_status = PHASE_COMPLETE; - ide->sc->callback = 0.0; + if (left) { + ide_atapi_callback(ide); + ide_set_callback(ide, 0.0); + } else { + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; - if (ide->phase_data_out != NULL) - (void) ide->phase_data_out(dev); + if (ide->phase_data_out != NULL) + (void) ide->phase_data_out(dev); - ide_atapi_callback(ide); + ide_atapi_callback(ide); + } } } else { if (dev->sector_len == 0) { - if (ide->command_stop != NULL) - ide->command_stop(dev); + if (left) { + ide_atapi_callback(ide); + ide_set_callback(ide, 0.0); + } else { + if (ide->command_stop != NULL) + ide->command_stop(dev); - ide->sc->packet_status = PHASE_COMPLETE; - ide->sc->callback = 0.0; + ide->sc->packet_status = PHASE_COMPLETE; + ide->sc->callback = 0.0; - ide_atapi_callback(ide); + ide_atapi_callback(ide); + } } else if (ide->read != NULL) ide->read(dev); } From 2019af174f9949bdc1017e95e02d206fb6ed0621 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 17 Mar 2025 22:53:00 +0600 Subject: [PATCH 042/158] Revert "C&T 69000: Fix bad refresh rate" This reverts commit b1a77195abe7b513583010b383a7f9ae317a16d2. --- src/video/vid_chips_69000.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 29521d1ae..8963cb94b 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -1428,6 +1428,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.bytes_skip = 0; chips->bitblt_running.mono_bytes_pitch = 0; chips->bitblt_running.mono_bits_skip_left = 0; + int orig_cycles = cycles; if (chips->bitblt.bitblt_control & (1 << 23)) { chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3); @@ -1631,6 +1632,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; } while ((++chips->bitblt_running.count_y) < chips->bitblt_running.actual_destination_height); + cycles = orig_cycles; chips_69000_bitblt_interrupt(chips); } @@ -1642,6 +1644,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } if (chips->bitblt_running.bitblt.bitblt_control & (1 << 12)) { + int orig_cycles = cycles; chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bitblt.monochrome_source_alignment == 1) { uint8_t val = chips->bitblt_running.bytes_port[0]; @@ -1659,6 +1662,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(chips->bitblt_running.bytes_port[j] & (1 << (7 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; return; } } @@ -1674,6 +1678,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (7 - i)))); if (orig_count_y != chips->bitblt_running.count_y && chips->bitblt_running.bitblt.monochrome_source_alignment != 1) { + cycles = orig_cycles; return; } } @@ -1687,6 +1692,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 16; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (15 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; return; } } @@ -1700,6 +1706,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 32; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (31 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; return; } } @@ -1722,10 +1729,12 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { for (i = 0; i < 64; i++) { chips_69000_process_mono_bit(chips, !!(val & (1 << (63 - i)))); if (orig_count_y != chips->bitblt_running.count_y) { + cycles = orig_cycles; return; } } } + cycles = orig_cycles; return; } @@ -1735,6 +1744,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { } chips->bitblt_running.bytes_port[chips->bitblt_running.bytes_written++] = data; if (chips->bitblt_running.bytes_written == chips->bitblt_running.bytes_per_pixel) { + int orig_cycles = cycles; uint32_t source_pixel = chips->bitblt_running.bytes_port[0]; chips->bitblt_running.bytes_written = 0; if (chips->bitblt_running.bytes_per_pixel >= 2) @@ -1745,6 +1755,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; chips_69000_process_pixel(chips, source_pixel); + cycles = orig_cycles; chips->bitblt_running.x += chips->bitblt_running.x_dir; if (chips->bitblt_running.bytes_in_line_written >= chips->bitblt_running.bitblt.destination_width) { @@ -2735,7 +2746,7 @@ chips_69000_getclock(int clock, void *priv) int pl = ((chips->ext_regs[0xcb] >> 4) & 7); float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); - if (!(chips->ext_regs[0xcb] & 4)) + if (chips->ext_regs[0xcb] & 4) fvco *= 4.0; float fo = fvco / (float)(1 << pl); @@ -2835,7 +2846,7 @@ chips_69000_init(const device_t *info) chips->svga.bpp = 8; chips->svga.miscout = 1; - chips->svga.vsync_callback = chips_69000_vblank_start; + chips->svga.vblank_start = chips_69000_vblank_start; chips->svga.getclock = chips_69000_getclock; chips->svga.conv_16to32 = chips_69000_conv_16to32; chips->svga.line_compare = chips_69000_line_compare; From 65020a80c88801581d1400f23dfe515fa85b7195 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 17 Mar 2025 22:53:36 +0600 Subject: [PATCH 043/158] Revert "C&T 69000: All ROPs now implemented, also fixed transparency bitblts" This reverts commit 000af483f3e0561fbb4c214496d20d0be358359b. --- src/video/vid_chips_69000.c | 1342 +++++++++++++---------------------- 1 file changed, 509 insertions(+), 833 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 8963cb94b..0347435fa 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -252,797 +252,486 @@ chips_69000_bitblt_interrupt(chips_69000_t* chips) chips_69000_interrupt(chips); } -#define ROPMIX(R, D, P, S, out) \ - { \ - switch (R) { \ - case 0x00: \ - out = 0; \ - break; \ - case 0x01: \ - out = ~(D | (P | S)); \ - break; \ - case 0x02: \ - out = D & ~(P | S); \ - break; \ - case 0x03: \ - out = ~(P | S); \ - break; \ - case 0x04: \ - out = S & ~(D | P); \ - break; \ - case 0x05: \ - out = ~(D | P); \ - break; \ - case 0x06: \ - out = ~(P | ~(D ^ S)); \ - break; \ - case 0x07: \ - out = ~(P | (D & S)); \ - break; \ - case 0x08: \ - out = S & (D & ~P); \ - break; \ - case 0x09: \ - out = ~(P | (D ^ S)); \ - break; \ - case 0x0a: \ - out = D & ~P; \ - break; \ - case 0x0b: \ - out = ~(P | (S & ~D)); \ - break; \ - case 0x0c: \ - out = S & ~P; \ - break; \ - case 0x0d: \ - out = ~(P | (D & ~S)); \ - break; \ - case 0x0e: \ - out = ~(P | ~(D | S)); \ - break; \ - case 0x0f: \ - out = ~P; \ - break; \ - case 0x10: \ - out = P & ~(D | S); \ - break; \ - case 0x11: \ - out = ~(D | S); \ - break; \ - case 0x12: \ - out = ~(S | ~(D ^ P)); \ - break; \ - case 0x13: \ - out = ~(S | (D & P)); \ - break; \ - case 0x14: \ - out = ~(D | ~(P ^ S)); \ - break; \ - case 0x15: \ - out = ~(D | (P & S)); \ - break; \ - case 0x16: \ - out = P ^ (S ^ (D & ~(P & S))); \ - break; \ - case 0x17: \ - out = ~(S ^ ((S ^ P) & (D ^ S))); \ - break; \ - case 0x18: \ - out = (S ^ P) & (P ^ D); \ - break; \ - case 0x19: \ - out = ~(S ^ (D & ~(P & S))); \ - break; \ - case 0x1a: \ - out = P ^ (D | (S & P)); \ - break; \ - case 0x1b: \ - out = ~(S ^ (D & (P ^ S))); \ - break; \ - case 0x1c: \ - out = P ^ (S | (D & P)); \ - break; \ - case 0x1d: \ - out = ~(D ^ (S & (P ^ D))); \ - break; \ - case 0x1e: \ - out = P ^ (D | S); \ - break; \ - case 0x1f: \ - out = ~(P & (D | S)); \ - break; \ - case 0x20: \ - out = D & (P & ~S); \ - break; \ - case 0x21: \ - out = ~(S | (D ^ P)); \ - break; \ - case 0x22: \ - out = D & ~S; \ - break; \ - case 0x23: \ - out = ~(S | (P & ~D)); \ - break; \ - case 0x24: \ - out = (S ^ P) & (D ^ S); \ - break; \ - case 0x25: \ - out = ~(P ^ (D & ~(S & P))); \ - break; \ - case 0x26: \ - out = S ^ (D | (P & S)); \ - break; \ - case 0x27: \ - out = S ^ (D | ~(P ^ S)); \ - break; \ - case 0x28: \ - out = D & (P ^ S); \ - break; \ - case 0x29: \ - out = ~(P ^ (S ^ (D | (P & S)))); \ - break; \ - case 0x2a: \ - out = D & ~(P & S); \ - break; \ - case 0x2b: \ - out = ~(S ^ ((S ^ P) & (P ^ D))); \ - break; \ - case 0x2c: \ - out = S ^ (P & (D | S)); \ - break; \ - case 0x2d: \ - out = P ^ (S | ~D); \ - break; \ - case 0x2e: \ - out = P ^ (S | (D ^ P)); \ - break; \ - case 0x2f: \ - out = ~(P & (S | ~D)); \ - break; \ - case 0x30: \ - out = P & ~S; \ - break; \ - case 0x31: \ - out = ~(S | (D & ~P)); \ - break; \ - case 0x32: \ - out = S ^ (D | (P | S)); \ - break; \ - case 0x33: \ - out = ~S; \ - break; \ - case 0x34: \ - out = S ^ (P | (D & S)); \ - break; \ - case 0x35: \ - out = S ^ (P | ~(D ^ S)); \ - break; \ - case 0x36: \ - out = S ^ (D | P); \ - break; \ - case 0x37: \ - out = ~(S & (D | P)); \ - break; \ - case 0x38: \ - out = P ^ (S & (D | P)); \ - break; \ - case 0x39: \ - out = S ^ (P | ~D); \ - break; \ - case 0x3a: \ - out = S ^ (P | (D ^ S)); \ - break; \ - case 0x3b: \ - out = ~(S & (P | ~D)); \ - break; \ - case 0x3c: \ - out = P ^ S; \ - break; \ - case 0x3d: \ - out = S ^ (P | ~(D | S)); \ - break; \ - case 0x3e: \ - out = S ^ (P | (D & ~S)); \ - break; \ - case 0x3f: \ - out = ~(P & S); \ - break; \ - case 0x40: \ - out = P & (S & ~D); \ - break; \ - case 0x41: \ - out = ~(D | (P ^ S)); \ - break; \ - case 0x42: \ - out = (S ^ D) & (P ^ D); \ - break; \ - case 0x43: \ - out = ~(S ^ (P & ~(D & S))); \ - break; \ - case 0x44: \ - out = S & ~D; \ - break; \ - case 0x45: \ - out = ~(D | (P & ~S)); \ - break; \ - case 0x46: \ - out = D ^ (S | (P & D)); \ - break; \ - case 0x47: \ - out = ~(P ^ (S & (D ^ P))); \ - break; \ - case 0x48: \ - out = S & (D ^ P); \ - break; \ - case 0x49: \ - out = ~(P ^ (D ^ (S | (P & D)))); \ - break; \ - case 0x4a: \ - out = D ^ (P & (S | D)); \ - break; \ - case 0x4b: \ - out = P ^ (D | ~S); \ - break; \ - case 0x4c: \ - out = S & ~(D & P); \ - break; \ - case 0x4d: \ - out = ~(S ^ ((S ^ P) | (D ^ S))); \ - break; \ - case 0x4e: \ - out = P ^ (D | (S ^ P)); \ - break; \ - case 0x4f: \ - out = ~(P & (D | ~S)); \ - break; \ - case 0x50: \ - out = P & ~D; \ - break; \ - case 0x51: \ - out = ~(D | (S & ~P)); \ - break; \ - case 0x52: \ - out = D ^ (P | (S & D)); \ - break; \ - case 0x53: \ - out = ~(S ^ (P & (D ^ S))); \ - break; \ - case 0x54: \ - out = ~(D | ~(P | S)); \ - break; \ - case 0x55: \ - out = ~D; \ - break; \ - case 0x56: \ - out = D ^ (P | S); \ - break; \ - case 0x57: \ - out = ~(D & (P | S)); \ - break; \ - case 0x58: \ - out = P ^ (D & (S | P)); \ - break; \ - case 0x59: \ - out = D ^ (P | ~S); \ - break; \ - case 0x5a: \ - out = D ^ P; \ - break; \ - case 0x5b: \ - out = D ^ (P | ~(S | D)); \ - break; \ - case 0x5c: \ - out = D ^ (P | (S ^ D)); \ - break; \ - case 0x5d: \ - out = ~(D & (P | ~S)); \ - break; \ - case 0x5e: \ - out = D ^ (P | (S & ~D)); \ - break; \ - case 0x5f: \ - out = ~(D & P); \ - break; \ - case 0x60: \ - out = P & (D ^ S); \ - break; \ - case 0x61: \ - out = ~(D ^ (S ^ (P | (D & S)))); \ - break; \ - case 0x62: \ - out = D ^ (S & (P | D)); \ - break; \ - case 0x63: \ - out = S ^ (D | ~P); \ - break; \ - case 0x64: \ - out = S ^ (D & (P | S)); \ - break; \ - case 0x65: \ - out = D ^ (S | ~P); \ - break; \ - case 0x66: \ - out = D ^ S; \ - break; \ - case 0x67: \ - out = S ^ (D | ~(P | S)); \ - break; \ - case 0x68: \ - out = ~(D ^ (S ^ (P | ~(D | S)))); \ - break; \ - case 0x69: \ - out = ~(P ^ (D ^ S)); \ - break; \ - case 0x6a: \ - out = D ^ (P & S); \ - break; \ - case 0x6b: \ - out = ~(P ^ (S ^ (D & (P | S)))); \ - break; \ - case 0x6c: \ - out = S ^ (D & P); \ - break; \ - case 0x6d: \ - out = ~(P ^ (D ^ (S & (P | D)))); \ - break; \ - case 0x6e: \ - out = S ^ (D & (P | ~S)); \ - break; \ - case 0x6f: \ - out = ~(P & ~(D ^ S)); \ - break; \ - case 0x70: \ - out = P & ~(D & S); \ - break; \ - case 0x71: \ - out = ~(S ^ ((S ^ D) & (P ^ D))); \ - break; \ - case 0x72: \ - out = S ^ (D | (P ^ S)); \ - break; \ - case 0x73: \ - out = ~(S & (D | ~P)); \ - break; \ - case 0x74: \ - out = D ^ (S | (P ^ D)); \ - break; \ - case 0x75: \ - out = ~(D & (S | ~P)); \ - break; \ - case 0x76: \ - out = S ^ (D | (P & ~S)); \ - break; \ - case 0x77: \ - out = ~(D & S); \ - break; \ - case 0x78: \ - out = P ^ (D & S); \ - break; \ - case 0x79: \ - out = ~(D ^ (S ^ (P & (D | S)))); \ - break; \ - case 0x7a: \ - out = D ^ (P & (S | ~D)); \ - break; \ - case 0x7b: \ - out = ~(S & ~(D ^ P)); \ - break; \ - case 0x7c: \ - out = S ^ (P & (D | ~S)); \ - break; \ - case 0x7d: \ - out = ~(D & ~(P ^ S)); \ - break; \ - case 0x7e: \ - out = (S ^ P) | (D ^ S); \ - break; \ - case 0x7f: \ - out = ~(D & (P & S)); \ - break; \ - case 0x80: \ - out = D & (P & S); \ - break; \ - case 0x81: \ - out = ~((S ^ P) | (D ^ S)); \ - break; \ - case 0x82: \ - out = D & ~(P ^ S); \ - break; \ - case 0x83: \ - out = ~(S ^ (P & (D | ~S))); \ - break; \ - case 0x84: \ - out = S & ~(D ^ P); \ - break; \ - case 0x85: \ - out = ~(P ^ (D & (S | ~P))); \ - break; \ - case 0x86: \ - out = D ^ (S ^ (P & (D | S))); \ - break; \ - case 0x87: \ - out = ~(P ^ (D & S)); \ - break; \ - case 0x88: \ - out = D & S; \ - break; \ - case 0x89: \ - out = ~(S ^ (D | (P & ~S))); \ - break; \ - case 0x8a: \ - out = D & (S | ~P); \ - break; \ - case 0x8b: \ - out = ~(D ^ (S | (P ^ D))); \ - break; \ - case 0x8c: \ - out = S & (D | ~P); \ - break; \ - case 0x8d: \ - out = ~(S ^ (D | (P ^ S))); \ - break; \ - case 0x8e: \ - out = S ^ ((S ^ D) & (P ^ D)); \ - break; \ - case 0x8f: \ - out = ~(P & ~(D & S)); \ - break; \ - case 0x90: \ - out = P & ~(D ^ S); \ - break; \ - case 0x91: \ - out = ~(S ^ (D & (P | ~S))); \ - break; \ - case 0x92: \ - out = D ^ (P ^ (S & (D | P))); \ - break; \ - case 0x93: \ - out = ~(S ^ (P & D)); \ - break; \ - case 0x94: \ - out = P ^ (S ^ (D & (P | S))); \ - break; \ - case 0x95: \ - out = ~(D ^ (P & S)); \ - break; \ - case 0x96: \ - out = D ^ (P ^ S); \ - break; \ - case 0x97: \ - out = P ^ (S ^ (D | ~(P | S))); \ - break; \ - case 0x98: \ - out = ~(S ^ (D | ~(P | S))); \ - break; \ - case 0x99: \ - out = ~(D ^ S); \ - break; \ - case 0x9a: \ - out = D ^ (P & ~S); \ - break; \ - case 0x9b: \ - out = ~(S ^ (D & (P | S))); \ - break; \ - case 0x9c: \ - out = S ^ (P & ~D); \ - break; \ - case 0x9d: \ - out = ~(D ^ (S & (P | D))); \ - break; \ - case 0x9e: \ - out = D ^ (S ^ (P | (D & S))); \ - break; \ - case 0x9f: \ - out = ~(P & (D ^ S)); \ - break; \ - case 0xa0: \ - out = D & P; \ - break; \ - case 0xa1: \ - out = ~(P ^ (D | (S & ~P))); \ - break; \ - case 0xa2: \ - out = D & (P | ~S); \ - break; \ - case 0xa3: \ - out = ~(D ^ (P | (S ^ D))); \ - break; \ - case 0xa4: \ - out = ~(P ^ (D | ~(S | P))); \ - break; \ - case 0xa5: \ - out = ~(P ^ D); \ - break; \ - case 0xa6: \ - out = D ^ (S & ~P); \ - break; \ - case 0xa7: \ - out = ~(P ^ (D & (S | P))); \ - break; \ - case 0xa8: \ - out = D & (P | S); \ - break; \ - case 0xa9: \ - out = ~(D ^ (P | S)); \ - break; \ - case 0xaa: \ - out = D; \ - break; \ - case 0xab: \ - out = D | ~(P | S); \ - break; \ - case 0xac: \ - out = S ^ (P & (D ^ S)); \ - break; \ - case 0xad: \ - out = ~(D ^ (P | (S & D))); \ - break; \ - case 0xae: \ - out = D | (S & ~P); \ - break; \ - case 0xaf: \ - out = D | ~P; \ - break; \ - case 0xb0: \ - out = P & (D | ~S); \ - break; \ - case 0xb1: \ - out = ~(P ^ (D | (S ^ P))); \ - break; \ - case 0xb2: \ - out = S ^ ((S ^ P) | (D ^ S)); \ - break; \ - case 0xb3: \ - out = ~(S & ~(D & P)); \ - break; \ - case 0xb4: \ - out = P ^ (S & ~D); \ - break; \ - case 0xb5: \ - out = ~(D ^ (P & (S | D))); \ - break; \ - case 0xb6: \ - out = D ^ (P ^ (S | (D & P))); \ - break; \ - case 0xb7: \ - out = ~(S & (D ^ P)); \ - break; \ - case 0xb8: \ - out = P ^ (S & (D ^ P)); \ - break; \ - case 0xb9: \ - out = ~(D ^ (S | (P & D))); \ - break; \ - case 0xba: \ - out = D | (P & ~S); \ - break; \ - case 0xbb: \ - out = D | ~S; \ - break; \ - case 0xbc: \ - out = S ^ (P & ~(D & S)); \ - break; \ - case 0xbd: \ - out = ~((S ^ D) & (P ^ D)); \ - break; \ - case 0xbe: \ - out = D | (P ^ S); \ - break; \ - case 0xbf: \ - out = D | ~(P & S); \ - break; \ - case 0xc0: \ - out = P & S; \ - break; \ - case 0xc1: \ - out = ~(S ^ (P | (D & ~S))); \ - break; \ - case 0xc2: \ - out = ~(S ^ (P | ~(D | S))); \ - break; \ - case 0xc3: \ - out = ~(P ^ S); \ - break; \ - case 0xc4: \ - out = S & (P | ~D); \ - break; \ - case 0xc5: \ - out = ~(S ^ (P | (D ^ S))); \ - break; \ - case 0xc6: \ - out = S ^ (D & ~P); \ - break; \ - case 0xc7: \ - out = ~(P ^ (S & (D | P))); \ - break; \ - case 0xc8: \ - out = S & (D | P); \ - break; \ - case 0xc9: \ - out = ~(S ^ (P | D)); \ - break; \ - case 0xca: \ - out = D ^ (P & (S ^ D)); \ - break; \ - case 0xcb: \ - out = ~(S ^ (P | (D & S))); \ - break; \ - case 0xcc: \ - out = S; \ - break; \ - case 0xcd: \ - out = S | ~(D | P); \ - break; \ - case 0xce: \ - out = S | (D & ~P); \ - break; \ - case 0xcf: \ - out = S | ~P; \ - break; \ - case 0xd0: \ - out = P & (S | ~D); \ - break; \ - case 0xd1: \ - out = ~(P ^ (S | (D ^ P))); \ - break; \ - case 0xd2: \ - out = P ^ (D & ~S); \ - break; \ - case 0xd3: \ - out = ~(S ^ (P & (D | S))); \ - break; \ - case 0xd4: \ - out = S ^ ((S ^ P) & (P ^ D)); \ - break; \ - case 0xd5: \ - out = ~(D & ~(P & S)); \ - break; \ - case 0xd6: \ - out = P ^ (S ^ (D | (P & S))); \ - break; \ - case 0xd7: \ - out = ~(D & (P ^ S)); \ - break; \ - case 0xd8: \ - out = P ^ (D & (S ^ P)); \ - break; \ - case 0xd9: \ - out = ~(S ^ (D | (P & S))); \ - break; \ - case 0xda: \ - out = D ^ (P & ~(S & D)); \ - break; \ - case 0xdb: \ - out = ~((S ^ P) & (D ^ S)); \ - break; \ - case 0xdc: \ - out = S | (P & ~D); \ - break; \ - case 0xdd: \ - out = S | ~D; \ - break; \ - case 0xde: \ - out = S | (D ^ P); \ - break; \ - case 0xdf: \ - out = S | ~(D & P); \ - break; \ - case 0xe0: \ - out = P & (D | S); \ - break; \ - case 0xe1: \ - out = ~(P ^ (D | S)); \ - break; \ - case 0xe2: \ - out = D ^ (S & (P ^ D)); \ - break; \ - case 0xe3: \ - out = ~(P ^ (S | (D & P))); \ - break; \ - case 0xe4: \ - out = S ^ (D & (P ^ S)); \ - break; \ - case 0xe5: \ - out = ~(P ^ (D | (S & P))); \ - break; \ - case 0xe6: \ - out = S ^ (D & ~(P & S)); \ - break; \ - case 0xe7: \ - out = ~((S ^ P) & (P ^ D)); \ - break; \ - case 0xe8: \ - out = S ^ ((S ^ P) & (D ^ S)); \ - break; \ - case 0xe9: \ - out = ~(D ^ (S ^ (P & ~(D & S)))); \ - break; \ - case 0xea: \ - out = D | (P & S); \ - break; \ - case 0xeb: \ - out = D | ~(P ^ S); \ - break; \ - case 0xec: \ - out = S | (D & P); \ - break; \ - case 0xed: \ - out = S | ~(D ^ P); \ - break; \ - case 0xee: \ - out = D | S; \ - break; \ - case 0xef: \ - out = S | (D | ~P); \ - break; \ - case 0xf0: \ - out = P; \ - break; \ - case 0xf1: \ - out = P | ~(D | S); \ - break; \ - case 0xf2: \ - out = P | (D & ~S); \ - break; \ - case 0xf3: \ - out = P | ~S; \ - break; \ - case 0xf4: \ - out = P | (S & ~D); \ - break; \ - case 0xf5: \ - out = P | ~D; \ - break; \ - case 0xf6: \ - out = P | (D ^ S); \ - break; \ - case 0xf7: \ - out = P | ~(D & S); \ - break; \ - case 0xf8: \ - out = P | (D & S); \ - break; \ - case 0xf9: \ - out = P | ~(D ^ S); \ - break; \ - case 0xfa: \ - out = D | P; \ - break; \ - case 0xfb: \ - out = D | (P | ~S); \ - break; \ - case 0xfc: \ - out = P | S; \ - break; \ - case 0xfd: \ - out = P | (S | ~D); \ - break; \ - case 0xfe: \ - out = D | (P | S); \ - break; \ - case 0xff: \ - out = ~0; \ - break; \ - } \ +void +chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFF; + break; } +} + +void +chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFF; + break; + } +} + +void +chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) +{ + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x11: + *dst = ~(*dst) & ~src; + break; + case 0x22: + *dst &= ~src; + break; + case 0x33: + *dst = ~src; + break; + case 0x44: + *dst = src & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x66: + *dst ^= src; + break; + case 0x77: + *dst = ~src | ~(*dst); + break; + case 0x88: + *dst &= src; + break; + case 0x99: + *dst ^= ~src; + break; + case 0xAA: + break; /* No-op. */ + case 0xBB: + *dst |= ~src; + break; + case 0xCC: + *dst = src; + break; + case 0xDD: + *dst = src | ~(*dst); + break; + case 0xEE: + *dst |= src; + break; + case 0xFF: + *dst = 0xFFFFFF; + break; + } +} void chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) { - ROPMIX(rop, *dst, pattern, src, *dst); + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_8bpp(dst, src, rop); + } + + switch (rop) { + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + } } void chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) { - ROPMIX(rop, *dst, pattern, src, *dst); + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_16bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } } void chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src, uint8_t rop) { uint32_t orig_dst = *dst & 0xFF000000; - ROPMIX(rop, *dst, pattern, src, *dst); + + if ((rop & 0xF) == ((rop >> 4) & 0xF)) { + return chips_69000_do_rop_24bpp(dst, src, rop); + } + + switch (rop) { + default: + pclog("Unknown ROP 0x%X\n", rop); + break; + case 0x00: + *dst = 0; + break; + case 0x05: + *dst = ~(*dst) & ~pattern; + break; + case 0x0A: + *dst &= ~pattern; + break; + case 0x0F: + *dst = ~pattern; + break; + case 0x1A: + *dst = pattern ^ (*dst | (pattern & src)); + break; + case 0x2A: + *dst = *dst & (~(src & pattern)); + break; + case 0x3A: + *dst = src ^ (pattern | (*dst ^ src)); + break; + case 0x4A: + *dst = *dst ^ (pattern & (src | *dst)); + break; + case 0x50: + *dst = pattern & ~(*dst); + break; + case 0x55: + *dst = ~*dst; + break; + case 0x5A: + *dst ^= pattern; + break; + case 0x5F: + *dst = ~pattern | ~(*dst); + break; + case 0x6A: + *dst = *dst ^ (pattern & src); + break; + case 0x7A: + *dst = *dst ^ (pattern & (src | (~*dst))); + break; + case 0x8A: + *dst = *dst & (src | (~pattern)); + break; + case 0x9A: + *dst = *dst ^ (pattern & (~src)); + break; + case 0xB8: + *dst = (((pattern ^ *dst) & src) ^ pattern); + break; + case 0xA0: + *dst &= pattern; + break; + case 0xA5: + *dst ^= ~pattern; + break; + case 0xAA: + break; /* No-op. */ + case 0xAC: + *dst = src ^ (pattern & (*dst ^ src)); + break; + case 0xAF: + *dst |= ~pattern; + break; + case 0xBA: + *dst |= (pattern & ~src); + break; + case 0xCA: + *dst ^= (pattern & (src ^ *dst)); + break; + case 0xDA: + *dst ^= pattern & (~(src & *dst)); + break; + case 0xE2: + *dst ^= (src & (pattern ^ *dst)); + break; + case 0xEA: + *dst |= pattern & src; + break; + case 0xF0: + *dst = pattern; + break; + case 0xF5: + *dst = pattern | ~(*dst); + break; + case 0xFA: + *dst |= pattern; + break; + case 0xFF: + *dst = 0xFF; + break; + } *dst &= 0xFFFFFF; *dst |= orig_dst; } @@ -1207,22 +896,20 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - //dest_pixel = chips_69000_readb_linear(dest_addr, chips); - dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; + dest_pixel = chips_69000_readb_linear(dest_addr, chips); break; } case 2: /* 16 bits-per-pixel. */ { - //dest_pixel = *(uint16_t*)&chips->svga.vram[dest_addr & chips->svga.vram_mask]; - dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; - dest_pixel |= chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] << 8; + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; break; } case 3: /* 24 bits-per-pixel. */ { - dest_pixel = chips->svga.vram[dest_addr & chips->svga.vram_mask]; - dest_pixel |= chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] << 8; - dest_pixel |= chips->svga.vram[(dest_addr + 2) & chips->svga.vram_mask] << 16; + dest_pixel = chips_69000_readb_linear(dest_addr, chips); + dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8; + dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16; break; } } @@ -1235,7 +922,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19)) pattern_data = 0; else - pattern_data = chips->svga.vram[(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7)) & chips->svga.vram_mask]; //chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); + pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + ((vert_pat_alignment + (chips->bitblt_running.y & 7)) & 7), chips); is_true = !!(pattern_data & (1 << (7 - ((chips->bitblt_running.bitblt.destination_addr + chips->bitblt_running.x) & 7)))); @@ -1251,30 +938,32 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; } else { - uint32_t pattern_pixel_addr = 0; if (chips->bitblt_running.bytes_per_pixel == 1) { - pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr - + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) - + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7); - - pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7) + + (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7), chips); } if (chips->bitblt_running.bytes_per_pixel == 2) { - pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr - + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)); + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); - pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; - pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 1) & chips->svga.vram_mask] << 8; + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (2 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (2 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; } if (chips->bitblt_running.bytes_per_pixel == 3) { - pattern_pixel_addr = chips->bitblt_running.bitblt.pat_addr - + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) - + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)); + pattern_pixel = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)), chips); - pattern_pixel = chips->svga.vram[pattern_pixel_addr & chips->svga.vram_mask]; - pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 1) & chips->svga.vram_mask] << 8; - pattern_pixel |= chips->svga.vram[(pattern_pixel_addr + 2) & chips->svga.vram_mask] << 16; + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 1, chips) << 8; + + pattern_pixel |= chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + + (4 * 8 * ((vert_pat_alignment + chips->bitblt_running.y) & 7)) + + (3 * (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.x) & 7)) + 2, chips) << 16; } } if (chips->bitblt_running.bytes_per_pixel == 2) { @@ -1292,7 +981,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) : chips->bitblt_running.bitblt.pattern_source_key_bg; color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -1330,7 +1019,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -1342,21 +1031,20 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; - //chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); break; } case 2: /* 16 bits-per-pixel. */ { - chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; - chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] = (dest_pixel >> 8) & 0xFF; + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); break; } case 3: /* 24 bits-per-pixel. */ { - chips->svga.vram[dest_addr & chips->svga.vram_mask] = dest_pixel & 0xFF; - chips->svga.vram[(dest_addr + 1) & chips->svga.vram_mask] = (dest_pixel >> 8) & 0xFF; - chips->svga.vram[(dest_addr + 2) & chips->svga.vram_mask] = (dest_pixel >> 16) & 0xFF; + chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips); + chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips); break; } } @@ -1524,8 +1212,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) uint32_t orig_source_addr = chips->bitblt_running.bitblt.source_addr; while (orig_count_y == chips->bitblt_running.count_y) { int i = 0; - //uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); - uint8_t data = chips->svga.vram[orig_source_addr & chips->svga.vram_mask]; + uint8_t data = chips_69000_readb_linear(orig_source_addr, chips); orig_source_addr++; for (i = 0; i < 8; i++) { chips_69000_process_mono_bit(chips, !!(data & (1 << (7 - i)))); @@ -1544,15 +1231,14 @@ chips_69000_setup_bitblt(chips_69000_t* chips) case 1: /* Bit-aligned */ case 2: /* Byte-aligned */ { - //uint32_t data = chips_69000_readb_linear(source_addr, chips); - uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask]; + uint32_t data = chips_69000_readb_linear(source_addr, chips); chips_69000_bitblt_write(chips, data & 0xFF); source_addr += 1; break; } case 3: /* Word-aligned*/ { - uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8); + uint32_t data = chips_69000_readw_linear(source_addr, chips); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); source_addr += 2; @@ -1560,8 +1246,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } case 4: /* Doubleword-aligned*/ { - uint32_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8) - | (chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16) | (chips->svga.vram[(source_addr + 3) & chips->svga.vram_mask] << 24); + uint32_t data = chips_69000_readl_linear(source_addr, chips); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); @@ -1571,15 +1256,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) } case 5: /* Quadword-aligned*/ { - uint64_t data = chips->svga.vram[source_addr & chips->svga.vram_mask] - | (chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8) - | (chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16) - | (chips->svga.vram[(source_addr + 3) & chips->svga.vram_mask] << 24) - | ((uint64_t)chips->svga.vram[(source_addr + 4) & chips->svga.vram_mask] << 32ULL) - | ((uint64_t)chips->svga.vram[(source_addr + 5) & chips->svga.vram_mask] << 40ULL) - | ((uint64_t)chips->svga.vram[(source_addr + 6) & chips->svga.vram_mask] << 48ULL) - | ((uint64_t)chips->svga.vram[(source_addr + 7) & chips->svga.vram_mask] << 56ULL); - //uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); + uint64_t data = (uint64_t)chips_69000_readl_linear(source_addr, chips) | ((uint64_t)chips_69000_readl_linear(source_addr + 4, chips) << 32ull); chips_69000_bitblt_write(chips, data & 0xFF); chips_69000_bitblt_write(chips, (data >> 8) & 0xFF); chips_69000_bitblt_write(chips, (data >> 16) & 0xFF); @@ -1604,21 +1281,20 @@ chips_69000_setup_bitblt(chips_69000_t* chips) switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { - //pixel = chips_69000_readb_linear(source_addr, chips); - pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; + pixel = chips_69000_readb_linear(source_addr, chips); break; } case 2: /* 16 bits-per-pixel. */ { - pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; - pixel |= chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8; + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; break; } case 3: /* 24 bits-per-pixel. */ { - pixel = chips->svga.vram[source_addr & chips->svga.vram_mask]; - pixel |= chips->svga.vram[(source_addr + 1) & chips->svga.vram_mask] << 8; - pixel |= chips->svga.vram[(source_addr + 2) & chips->svga.vram_mask] << 16; + pixel = chips_69000_readb_linear(source_addr, chips); + pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8; + pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16; break; } } From 9182deaa2bf59c8d71b55a9a95ad551f557d9dc5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 17 Mar 2025 23:04:23 +0600 Subject: [PATCH 044/158] C&T B69000: Revert optimizations that made GUI acceleration slow --- src/video/vid_chips_69000.c | 1245 ++++++++++++++++++++++------------- 1 file changed, 779 insertions(+), 466 deletions(-) diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 0347435fa..d06ab0484 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -252,378 +252,790 @@ chips_69000_bitblt_interrupt(chips_69000_t* chips) chips_69000_interrupt(chips); } -void -chips_69000_do_rop_8bpp(uint8_t *dst, uint8_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFF; - break; +#define ROPMIX(R, D, P, S, out) \ + { \ + switch (R) { \ + case 0x00: \ + out = 0; \ + break; \ + case 0x01: \ + out = ~(D | (P | S)); \ + break; \ + case 0x02: \ + out = D & ~(P | S); \ + break; \ + case 0x03: \ + out = ~(P | S); \ + break; \ + case 0x04: \ + out = S & ~(D | P); \ + break; \ + case 0x05: \ + out = ~(D | P); \ + break; \ + case 0x06: \ + out = ~(P | ~(D ^ S)); \ + break; \ + case 0x07: \ + out = ~(P | (D & S)); \ + break; \ + case 0x08: \ + out = S & (D & ~P); \ + break; \ + case 0x09: \ + out = ~(P | (D ^ S)); \ + break; \ + case 0x0a: \ + out = D & ~P; \ + break; \ + case 0x0b: \ + out = ~(P | (S & ~D)); \ + break; \ + case 0x0c: \ + out = S & ~P; \ + break; \ + case 0x0d: \ + out = ~(P | (D & ~S)); \ + break; \ + case 0x0e: \ + out = ~(P | ~(D | S)); \ + break; \ + case 0x0f: \ + out = ~P; \ + break; \ + case 0x10: \ + out = P & ~(D | S); \ + break; \ + case 0x11: \ + out = ~(D | S); \ + break; \ + case 0x12: \ + out = ~(S | ~(D ^ P)); \ + break; \ + case 0x13: \ + out = ~(S | (D & P)); \ + break; \ + case 0x14: \ + out = ~(D | ~(P ^ S)); \ + break; \ + case 0x15: \ + out = ~(D | (P & S)); \ + break; \ + case 0x16: \ + out = P ^ (S ^ (D & ~(P & S))); \ + break; \ + case 0x17: \ + out = ~(S ^ ((S ^ P) & (D ^ S))); \ + break; \ + case 0x18: \ + out = (S ^ P) & (P ^ D); \ + break; \ + case 0x19: \ + out = ~(S ^ (D & ~(P & S))); \ + break; \ + case 0x1a: \ + out = P ^ (D | (S & P)); \ + break; \ + case 0x1b: \ + out = ~(S ^ (D & (P ^ S))); \ + break; \ + case 0x1c: \ + out = P ^ (S | (D & P)); \ + break; \ + case 0x1d: \ + out = ~(D ^ (S & (P ^ D))); \ + break; \ + case 0x1e: \ + out = P ^ (D | S); \ + break; \ + case 0x1f: \ + out = ~(P & (D | S)); \ + break; \ + case 0x20: \ + out = D & (P & ~S); \ + break; \ + case 0x21: \ + out = ~(S | (D ^ P)); \ + break; \ + case 0x22: \ + out = D & ~S; \ + break; \ + case 0x23: \ + out = ~(S | (P & ~D)); \ + break; \ + case 0x24: \ + out = (S ^ P) & (D ^ S); \ + break; \ + case 0x25: \ + out = ~(P ^ (D & ~(S & P))); \ + break; \ + case 0x26: \ + out = S ^ (D | (P & S)); \ + break; \ + case 0x27: \ + out = S ^ (D | ~(P ^ S)); \ + break; \ + case 0x28: \ + out = D & (P ^ S); \ + break; \ + case 0x29: \ + out = ~(P ^ (S ^ (D | (P & S)))); \ + break; \ + case 0x2a: \ + out = D & ~(P & S); \ + break; \ + case 0x2b: \ + out = ~(S ^ ((S ^ P) & (P ^ D))); \ + break; \ + case 0x2c: \ + out = S ^ (P & (D | S)); \ + break; \ + case 0x2d: \ + out = P ^ (S | ~D); \ + break; \ + case 0x2e: \ + out = P ^ (S | (D ^ P)); \ + break; \ + case 0x2f: \ + out = ~(P & (S | ~D)); \ + break; \ + case 0x30: \ + out = P & ~S; \ + break; \ + case 0x31: \ + out = ~(S | (D & ~P)); \ + break; \ + case 0x32: \ + out = S ^ (D | (P | S)); \ + break; \ + case 0x33: \ + out = ~S; \ + break; \ + case 0x34: \ + out = S ^ (P | (D & S)); \ + break; \ + case 0x35: \ + out = S ^ (P | ~(D ^ S)); \ + break; \ + case 0x36: \ + out = S ^ (D | P); \ + break; \ + case 0x37: \ + out = ~(S & (D | P)); \ + break; \ + case 0x38: \ + out = P ^ (S & (D | P)); \ + break; \ + case 0x39: \ + out = S ^ (P | ~D); \ + break; \ + case 0x3a: \ + out = S ^ (P | (D ^ S)); \ + break; \ + case 0x3b: \ + out = ~(S & (P | ~D)); \ + break; \ + case 0x3c: \ + out = P ^ S; \ + break; \ + case 0x3d: \ + out = S ^ (P | ~(D | S)); \ + break; \ + case 0x3e: \ + out = S ^ (P | (D & ~S)); \ + break; \ + case 0x3f: \ + out = ~(P & S); \ + break; \ + case 0x40: \ + out = P & (S & ~D); \ + break; \ + case 0x41: \ + out = ~(D | (P ^ S)); \ + break; \ + case 0x42: \ + out = (S ^ D) & (P ^ D); \ + break; \ + case 0x43: \ + out = ~(S ^ (P & ~(D & S))); \ + break; \ + case 0x44: \ + out = S & ~D; \ + break; \ + case 0x45: \ + out = ~(D | (P & ~S)); \ + break; \ + case 0x46: \ + out = D ^ (S | (P & D)); \ + break; \ + case 0x47: \ + out = ~(P ^ (S & (D ^ P))); \ + break; \ + case 0x48: \ + out = S & (D ^ P); \ + break; \ + case 0x49: \ + out = ~(P ^ (D ^ (S | (P & D)))); \ + break; \ + case 0x4a: \ + out = D ^ (P & (S | D)); \ + break; \ + case 0x4b: \ + out = P ^ (D | ~S); \ + break; \ + case 0x4c: \ + out = S & ~(D & P); \ + break; \ + case 0x4d: \ + out = ~(S ^ ((S ^ P) | (D ^ S))); \ + break; \ + case 0x4e: \ + out = P ^ (D | (S ^ P)); \ + break; \ + case 0x4f: \ + out = ~(P & (D | ~S)); \ + break; \ + case 0x50: \ + out = P & ~D; \ + break; \ + case 0x51: \ + out = ~(D | (S & ~P)); \ + break; \ + case 0x52: \ + out = D ^ (P | (S & D)); \ + break; \ + case 0x53: \ + out = ~(S ^ (P & (D ^ S))); \ + break; \ + case 0x54: \ + out = ~(D | ~(P | S)); \ + break; \ + case 0x55: \ + out = ~D; \ + break; \ + case 0x56: \ + out = D ^ (P | S); \ + break; \ + case 0x57: \ + out = ~(D & (P | S)); \ + break; \ + case 0x58: \ + out = P ^ (D & (S | P)); \ + break; \ + case 0x59: \ + out = D ^ (P | ~S); \ + break; \ + case 0x5a: \ + out = D ^ P; \ + break; \ + case 0x5b: \ + out = D ^ (P | ~(S | D)); \ + break; \ + case 0x5c: \ + out = D ^ (P | (S ^ D)); \ + break; \ + case 0x5d: \ + out = ~(D & (P | ~S)); \ + break; \ + case 0x5e: \ + out = D ^ (P | (S & ~D)); \ + break; \ + case 0x5f: \ + out = ~(D & P); \ + break; \ + case 0x60: \ + out = P & (D ^ S); \ + break; \ + case 0x61: \ + out = ~(D ^ (S ^ (P | (D & S)))); \ + break; \ + case 0x62: \ + out = D ^ (S & (P | D)); \ + break; \ + case 0x63: \ + out = S ^ (D | ~P); \ + break; \ + case 0x64: \ + out = S ^ (D & (P | S)); \ + break; \ + case 0x65: \ + out = D ^ (S | ~P); \ + break; \ + case 0x66: \ + out = D ^ S; \ + break; \ + case 0x67: \ + out = S ^ (D | ~(P | S)); \ + break; \ + case 0x68: \ + out = ~(D ^ (S ^ (P | ~(D | S)))); \ + break; \ + case 0x69: \ + out = ~(P ^ (D ^ S)); \ + break; \ + case 0x6a: \ + out = D ^ (P & S); \ + break; \ + case 0x6b: \ + out = ~(P ^ (S ^ (D & (P | S)))); \ + break; \ + case 0x6c: \ + out = S ^ (D & P); \ + break; \ + case 0x6d: \ + out = ~(P ^ (D ^ (S & (P | D)))); \ + break; \ + case 0x6e: \ + out = S ^ (D & (P | ~S)); \ + break; \ + case 0x6f: \ + out = ~(P & ~(D ^ S)); \ + break; \ + case 0x70: \ + out = P & ~(D & S); \ + break; \ + case 0x71: \ + out = ~(S ^ ((S ^ D) & (P ^ D))); \ + break; \ + case 0x72: \ + out = S ^ (D | (P ^ S)); \ + break; \ + case 0x73: \ + out = ~(S & (D | ~P)); \ + break; \ + case 0x74: \ + out = D ^ (S | (P ^ D)); \ + break; \ + case 0x75: \ + out = ~(D & (S | ~P)); \ + break; \ + case 0x76: \ + out = S ^ (D | (P & ~S)); \ + break; \ + case 0x77: \ + out = ~(D & S); \ + break; \ + case 0x78: \ + out = P ^ (D & S); \ + break; \ + case 0x79: \ + out = ~(D ^ (S ^ (P & (D | S)))); \ + break; \ + case 0x7a: \ + out = D ^ (P & (S | ~D)); \ + break; \ + case 0x7b: \ + out = ~(S & ~(D ^ P)); \ + break; \ + case 0x7c: \ + out = S ^ (P & (D | ~S)); \ + break; \ + case 0x7d: \ + out = ~(D & ~(P ^ S)); \ + break; \ + case 0x7e: \ + out = (S ^ P) | (D ^ S); \ + break; \ + case 0x7f: \ + out = ~(D & (P & S)); \ + break; \ + case 0x80: \ + out = D & (P & S); \ + break; \ + case 0x81: \ + out = ~((S ^ P) | (D ^ S)); \ + break; \ + case 0x82: \ + out = D & ~(P ^ S); \ + break; \ + case 0x83: \ + out = ~(S ^ (P & (D | ~S))); \ + break; \ + case 0x84: \ + out = S & ~(D ^ P); \ + break; \ + case 0x85: \ + out = ~(P ^ (D & (S | ~P))); \ + break; \ + case 0x86: \ + out = D ^ (S ^ (P & (D | S))); \ + break; \ + case 0x87: \ + out = ~(P ^ (D & S)); \ + break; \ + case 0x88: \ + out = D & S; \ + break; \ + case 0x89: \ + out = ~(S ^ (D | (P & ~S))); \ + break; \ + case 0x8a: \ + out = D & (S | ~P); \ + break; \ + case 0x8b: \ + out = ~(D ^ (S | (P ^ D))); \ + break; \ + case 0x8c: \ + out = S & (D | ~P); \ + break; \ + case 0x8d: \ + out = ~(S ^ (D | (P ^ S))); \ + break; \ + case 0x8e: \ + out = S ^ ((S ^ D) & (P ^ D)); \ + break; \ + case 0x8f: \ + out = ~(P & ~(D & S)); \ + break; \ + case 0x90: \ + out = P & ~(D ^ S); \ + break; \ + case 0x91: \ + out = ~(S ^ (D & (P | ~S))); \ + break; \ + case 0x92: \ + out = D ^ (P ^ (S & (D | P))); \ + break; \ + case 0x93: \ + out = ~(S ^ (P & D)); \ + break; \ + case 0x94: \ + out = P ^ (S ^ (D & (P | S))); \ + break; \ + case 0x95: \ + out = ~(D ^ (P & S)); \ + break; \ + case 0x96: \ + out = D ^ (P ^ S); \ + break; \ + case 0x97: \ + out = P ^ (S ^ (D | ~(P | S))); \ + break; \ + case 0x98: \ + out = ~(S ^ (D | ~(P | S))); \ + break; \ + case 0x99: \ + out = ~(D ^ S); \ + break; \ + case 0x9a: \ + out = D ^ (P & ~S); \ + break; \ + case 0x9b: \ + out = ~(S ^ (D & (P | S))); \ + break; \ + case 0x9c: \ + out = S ^ (P & ~D); \ + break; \ + case 0x9d: \ + out = ~(D ^ (S & (P | D))); \ + break; \ + case 0x9e: \ + out = D ^ (S ^ (P | (D & S))); \ + break; \ + case 0x9f: \ + out = ~(P & (D ^ S)); \ + break; \ + case 0xa0: \ + out = D & P; \ + break; \ + case 0xa1: \ + out = ~(P ^ (D | (S & ~P))); \ + break; \ + case 0xa2: \ + out = D & (P | ~S); \ + break; \ + case 0xa3: \ + out = ~(D ^ (P | (S ^ D))); \ + break; \ + case 0xa4: \ + out = ~(P ^ (D | ~(S | P))); \ + break; \ + case 0xa5: \ + out = ~(P ^ D); \ + break; \ + case 0xa6: \ + out = D ^ (S & ~P); \ + break; \ + case 0xa7: \ + out = ~(P ^ (D & (S | P))); \ + break; \ + case 0xa8: \ + out = D & (P | S); \ + break; \ + case 0xa9: \ + out = ~(D ^ (P | S)); \ + break; \ + case 0xaa: \ + out = D; \ + break; \ + case 0xab: \ + out = D | ~(P | S); \ + break; \ + case 0xac: \ + out = S ^ (P & (D ^ S)); \ + break; \ + case 0xad: \ + out = ~(D ^ (P | (S & D))); \ + break; \ + case 0xae: \ + out = D | (S & ~P); \ + break; \ + case 0xaf: \ + out = D | ~P; \ + break; \ + case 0xb0: \ + out = P & (D | ~S); \ + break; \ + case 0xb1: \ + out = ~(P ^ (D | (S ^ P))); \ + break; \ + case 0xb2: \ + out = S ^ ((S ^ P) | (D ^ S)); \ + break; \ + case 0xb3: \ + out = ~(S & ~(D & P)); \ + break; \ + case 0xb4: \ + out = P ^ (S & ~D); \ + break; \ + case 0xb5: \ + out = ~(D ^ (P & (S | D))); \ + break; \ + case 0xb6: \ + out = D ^ (P ^ (S | (D & P))); \ + break; \ + case 0xb7: \ + out = ~(S & (D ^ P)); \ + break; \ + case 0xb8: \ + out = P ^ (S & (D ^ P)); \ + break; \ + case 0xb9: \ + out = ~(D ^ (S | (P & D))); \ + break; \ + case 0xba: \ + out = D | (P & ~S); \ + break; \ + case 0xbb: \ + out = D | ~S; \ + break; \ + case 0xbc: \ + out = S ^ (P & ~(D & S)); \ + break; \ + case 0xbd: \ + out = ~((S ^ D) & (P ^ D)); \ + break; \ + case 0xbe: \ + out = D | (P ^ S); \ + break; \ + case 0xbf: \ + out = D | ~(P & S); \ + break; \ + case 0xc0: \ + out = P & S; \ + break; \ + case 0xc1: \ + out = ~(S ^ (P | (D & ~S))); \ + break; \ + case 0xc2: \ + out = ~(S ^ (P | ~(D | S))); \ + break; \ + case 0xc3: \ + out = ~(P ^ S); \ + break; \ + case 0xc4: \ + out = S & (P | ~D); \ + break; \ + case 0xc5: \ + out = ~(S ^ (P | (D ^ S))); \ + break; \ + case 0xc6: \ + out = S ^ (D & ~P); \ + break; \ + case 0xc7: \ + out = ~(P ^ (S & (D | P))); \ + break; \ + case 0xc8: \ + out = S & (D | P); \ + break; \ + case 0xc9: \ + out = ~(S ^ (P | D)); \ + break; \ + case 0xca: \ + out = D ^ (P & (S ^ D)); \ + break; \ + case 0xcb: \ + out = ~(S ^ (P | (D & S))); \ + break; \ + case 0xcc: \ + out = S; \ + break; \ + case 0xcd: \ + out = S | ~(D | P); \ + break; \ + case 0xce: \ + out = S | (D & ~P); \ + break; \ + case 0xcf: \ + out = S | ~P; \ + break; \ + case 0xd0: \ + out = P & (S | ~D); \ + break; \ + case 0xd1: \ + out = ~(P ^ (S | (D ^ P))); \ + break; \ + case 0xd2: \ + out = P ^ (D & ~S); \ + break; \ + case 0xd3: \ + out = ~(S ^ (P & (D | S))); \ + break; \ + case 0xd4: \ + out = S ^ ((S ^ P) & (P ^ D)); \ + break; \ + case 0xd5: \ + out = ~(D & ~(P & S)); \ + break; \ + case 0xd6: \ + out = P ^ (S ^ (D | (P & S))); \ + break; \ + case 0xd7: \ + out = ~(D & (P ^ S)); \ + break; \ + case 0xd8: \ + out = P ^ (D & (S ^ P)); \ + break; \ + case 0xd9: \ + out = ~(S ^ (D | (P & S))); \ + break; \ + case 0xda: \ + out = D ^ (P & ~(S & D)); \ + break; \ + case 0xdb: \ + out = ~((S ^ P) & (D ^ S)); \ + break; \ + case 0xdc: \ + out = S | (P & ~D); \ + break; \ + case 0xdd: \ + out = S | ~D; \ + break; \ + case 0xde: \ + out = S | (D ^ P); \ + break; \ + case 0xdf: \ + out = S | ~(D & P); \ + break; \ + case 0xe0: \ + out = P & (D | S); \ + break; \ + case 0xe1: \ + out = ~(P ^ (D | S)); \ + break; \ + case 0xe2: \ + out = D ^ (S & (P ^ D)); \ + break; \ + case 0xe3: \ + out = ~(P ^ (S | (D & P))); \ + break; \ + case 0xe4: \ + out = S ^ (D & (P ^ S)); \ + break; \ + case 0xe5: \ + out = ~(P ^ (D | (S & P))); \ + break; \ + case 0xe6: \ + out = S ^ (D & ~(P & S)); \ + break; \ + case 0xe7: \ + out = ~((S ^ P) & (P ^ D)); \ + break; \ + case 0xe8: \ + out = S ^ ((S ^ P) & (D ^ S)); \ + break; \ + case 0xe9: \ + out = ~(D ^ (S ^ (P & ~(D & S)))); \ + break; \ + case 0xea: \ + out = D | (P & S); \ + break; \ + case 0xeb: \ + out = D | ~(P ^ S); \ + break; \ + case 0xec: \ + out = S | (D & P); \ + break; \ + case 0xed: \ + out = S | ~(D ^ P); \ + break; \ + case 0xee: \ + out = D | S; \ + break; \ + case 0xef: \ + out = S | (D | ~P); \ + break; \ + case 0xf0: \ + out = P; \ + break; \ + case 0xf1: \ + out = P | ~(D | S); \ + break; \ + case 0xf2: \ + out = P | (D & ~S); \ + break; \ + case 0xf3: \ + out = P | ~S; \ + break; \ + case 0xf4: \ + out = P | (S & ~D); \ + break; \ + case 0xf5: \ + out = P | ~D; \ + break; \ + case 0xf6: \ + out = P | (D ^ S); \ + break; \ + case 0xf7: \ + out = P | ~(D & S); \ + break; \ + case 0xf8: \ + out = P | (D & S); \ + break; \ + case 0xf9: \ + out = P | ~(D ^ S); \ + break; \ + case 0xfa: \ + out = D | P; \ + break; \ + case 0xfb: \ + out = D | (P | ~S); \ + break; \ + case 0xfc: \ + out = P | S; \ + break; \ + case 0xfd: \ + out = P | (S | ~D); \ + break; \ + case 0xfe: \ + out = D | (P | S); \ + break; \ + case 0xff: \ + out = ~0; \ + break; \ + } \ } -} - -void -chips_69000_do_rop_16bpp(uint16_t *dst, uint16_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFFFF; - break; - } -} - -void -chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop) -{ - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x11: - *dst = ~(*dst) & ~src; - break; - case 0x22: - *dst &= ~src; - break; - case 0x33: - *dst = ~src; - break; - case 0x44: - *dst = src & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x66: - *dst ^= src; - break; - case 0x77: - *dst = ~src | ~(*dst); - break; - case 0x88: - *dst &= src; - break; - case 0x99: - *dst ^= ~src; - break; - case 0xAA: - break; /* No-op. */ - case 0xBB: - *dst |= ~src; - break; - case 0xCC: - *dst = src; - break; - case 0xDD: - *dst = src | ~(*dst); - break; - case 0xEE: - *dst |= src; - break; - case 0xFF: - *dst = 0xFFFFFF; - break; - } -} void chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t pattern, uint8_t src, uint8_t rop) { - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_8bpp(dst, src, rop); - } - - switch (rop) { - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - } + ROPMIX(rop, *dst, pattern, src, *dst); } void chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t pattern, uint16_t src, uint8_t rop) { - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_16bpp(dst, src, rop); - } - - switch (rop) { - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - } + ROPMIX(rop, *dst, pattern, src, *dst); } void @@ -631,107 +1043,8 @@ chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t pattern, uint32_t src { uint32_t orig_dst = *dst & 0xFF000000; - if ((rop & 0xF) == ((rop >> 4) & 0xF)) { - return chips_69000_do_rop_24bpp(dst, src, rop); - } + ROPMIX(rop, *dst, pattern, src, *dst); - switch (rop) { - default: - pclog("Unknown ROP 0x%X\n", rop); - break; - case 0x00: - *dst = 0; - break; - case 0x05: - *dst = ~(*dst) & ~pattern; - break; - case 0x0A: - *dst &= ~pattern; - break; - case 0x0F: - *dst = ~pattern; - break; - case 0x1A: - *dst = pattern ^ (*dst | (pattern & src)); - break; - case 0x2A: - *dst = *dst & (~(src & pattern)); - break; - case 0x3A: - *dst = src ^ (pattern | (*dst ^ src)); - break; - case 0x4A: - *dst = *dst ^ (pattern & (src | *dst)); - break; - case 0x50: - *dst = pattern & ~(*dst); - break; - case 0x55: - *dst = ~*dst; - break; - case 0x5A: - *dst ^= pattern; - break; - case 0x5F: - *dst = ~pattern | ~(*dst); - break; - case 0x6A: - *dst = *dst ^ (pattern & src); - break; - case 0x7A: - *dst = *dst ^ (pattern & (src | (~*dst))); - break; - case 0x8A: - *dst = *dst & (src | (~pattern)); - break; - case 0x9A: - *dst = *dst ^ (pattern & (~src)); - break; - case 0xB8: - *dst = (((pattern ^ *dst) & src) ^ pattern); - break; - case 0xA0: - *dst &= pattern; - break; - case 0xA5: - *dst ^= ~pattern; - break; - case 0xAA: - break; /* No-op. */ - case 0xAC: - *dst = src ^ (pattern & (*dst ^ src)); - break; - case 0xAF: - *dst |= ~pattern; - break; - case 0xBA: - *dst |= (pattern & ~src); - break; - case 0xCA: - *dst ^= (pattern & (src ^ *dst)); - break; - case 0xDA: - *dst ^= pattern & (~(src & *dst)); - break; - case 0xE2: - *dst ^= (src & (pattern ^ *dst)); - break; - case 0xEA: - *dst |= pattern & src; - break; - case 0xF0: - *dst = pattern; - break; - case 0xF5: - *dst = pattern | ~(*dst); - break; - case 0xFA: - *dst |= pattern; - break; - case 0xFF: - *dst = 0xFF; - break; - } *dst &= 0xFFFFFF; *dst |= orig_dst; } @@ -981,7 +1294,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) : chips->bitblt_running.bitblt.pattern_source_key_bg; color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -1019,7 +1332,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) color_key &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; dest_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1; - if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { + if (!!(color_key == dest_pixel) == !(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } @@ -2422,7 +2735,7 @@ chips_69000_getclock(int clock, void *priv) int pl = ((chips->ext_regs[0xcb] >> 4) & 7); float fvco = 14318181.0 * ((float)(m + 2) / (float)(n + 2)); - if (chips->ext_regs[0xcb] & 4) + if (!(chips->ext_regs[0xcb] & 4)) fvco *= 4.0; float fo = fvco / (float)(1 << pl); @@ -2522,7 +2835,7 @@ chips_69000_init(const device_t *info) chips->svga.bpp = 8; chips->svga.miscout = 1; - chips->svga.vblank_start = chips_69000_vblank_start; + chips->svga.vsync_callback = chips_69000_vblank_start; chips->svga.getclock = chips_69000_getclock; chips->svga.conv_16to32 = chips_69000_conv_16to32; chips->svga.line_compare = chips_69000_line_compare; From 556c74c1599e2c279a29cade4d7ef233dd48e0aa Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 20:58:15 +0100 Subject: [PATCH 045/158] IDE DMA: Properly handle partial transfers, fixes ATAPI DMA in Windows 98 SE. --- src/disk/hdc_ide.c | 17 ++++++++++------- src/disk/hdc_ide_cmd646.c | 8 ++++---- src/disk/hdc_ide_sff8038i.c | 16 +++++++++++----- src/include/86box/hdc_ide.h | 2 +- src/include/86box/hdc_ide_sff8038i.h | 2 +- src/scsi/scsi_cdrom.c | 4 +++- 6 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index bf0d4d286..01690cd70 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -117,7 +117,7 @@ #define ROM_PATH_MCIDE "roms/hdd/xtide/ide_ps2 R1.1.bin" typedef struct ide_bm_t { - int (*dma)(uint8_t *data, int transfer_length, int out, void *priv); + int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv); void (*set_irq)(uint8_t status, void *priv); void *priv; } ide_bm_t; @@ -1094,7 +1094,7 @@ ide_atapi_callback(ide_t *ide) if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { if (ide->sc->block_len == 0) { - ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, bm->priv); + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 0, bm->priv); /* Underrun. */ if (ret == 1) @@ -1102,6 +1102,7 @@ ide_atapi_callback(ide_t *ide) } else { ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos - ide->sc->block_len, ide->sc->block_len, + ide->sc->sector_len * ide->sc->block_len, 0, bm->priv); if (ret == 1) { @@ -1144,14 +1145,16 @@ ide_atapi_callback(ide_t *ide) if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { if (ide->sc->block_len == 0) { - ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 1, bm->priv); + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 1, bm->priv); /* Underrun. */ if (ret == 1) ret = 3; } else { ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos, - ide->sc->block_len, 1, bm->priv); + ide->sc->block_len, + ide->sc->sector_len * ide->sc->block_len, + 1, bm->priv); if (ret & 1) { if (ide->write != NULL) @@ -2392,7 +2395,7 @@ ide_callback(void *priv) err = UNC_ERR; } else if (!ide_boards[ide->board]->force_ata3 && bm->dma) { /* We should not abort - we should simply wait for the host to start DMA. */ - ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, bm->priv); + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 0, bm->priv); if (ret == 2) { /* Bus master DMA disabled, simply wait for the host to enable DMA. */ ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; @@ -2500,7 +2503,7 @@ ide_callback(void *priv) else ide->sector_pos = 256; - ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 1, bm->priv); + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 1, bm->priv); if (ret == 2) { /* Bus master DMA disabled, simply wait for the host to enable DMA. */ @@ -3127,7 +3130,7 @@ ide_xtide_close(void) void ide_set_bus_master(int board, - int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv), void (*set_irq)(uint8_t status, void *priv), void *priv) { ide_bm_t *bm; diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index b548390fd..a60962ba8 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -95,19 +95,19 @@ cmd646_set_irq_1(uint8_t status, void *priv) } static int -cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int out, void *priv) +cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int total_length, int out, void *priv) { const cmd646_t *dev = (cmd646_t *) priv; - return sff_bus_master_dma(data, transfer_length, out, dev->bm[0]); + return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[0]); } static int -cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int out, void *priv) +cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int total_length, int out, void *priv) { const cmd646_t *dev = (cmd646_t *) priv; - return sff_bus_master_dma(data, transfer_length, out, dev->bm[1]); + return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[1]); } static void diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 2cc1fe72e..7ded4372f 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -316,14 +316,14 @@ sff_bus_master_readl(uint16_t port, void *priv) } int -sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv) +sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; #ifdef ENABLE_SFF_LOG char *sop; #endif - int force_end = 0; + int force_end = 0; int buffer_pos = 0; #ifdef ENABLE_SFF_LOG @@ -365,9 +365,15 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv) return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ } else { if (!transfer_length && !dev->eot) { - sff_log("Total transfer length smaller than sum of all blocks, full block\n"); - dev->status &= ~2; - return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ + if (total_length) { + sff_log("Total transfer length smaller than sum of all blocks, partial transfer\n"); + sff_bus_master_next_addr(dev); + return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } else { + sff_log("Total transfer length smaller than sum of all blocks, full block\n"); + dev->status &= ~2; + return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } } else if (transfer_length && dev->eot) { sff_log("Total transfer length greater than sum of all blocks\n"); dev->status |= 2; diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 4e4ea4e5b..41fb7703e 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -201,7 +201,7 @@ extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); extern uint16_t ide_readw(uint16_t addr, void *priv); extern void ide_set_bus_master(int board, - int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), + int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv), void (*set_irq)(uint8_t status, void *priv), void *priv); extern void win_cdrom_eject(uint8_t id); diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 3a69fdfac..79075b8b2 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -63,7 +63,7 @@ extern const device_t sff8038i_device; extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base); extern void sff_bus_master_set_irq(uint8_t status, void *priv); -extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv); +extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv); extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv); extern uint8_t sff_bus_master_read(uint16_t port, void *priv); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 292c54127..a8bb1513b 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1096,6 +1096,8 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev) int msf = 0; int type = dev->sector_type; int flags = dev->sector_flags; + int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? + dev->requested_blocks : 1; switch (dev->current_cdb[0]) { case GPCMD_READ_CD_MSF_OLD: @@ -1128,7 +1130,7 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev) } scsi_cdrom_log(dev->log, "Reading %i blocks starting from %i...\n", - dev->requested_blocks, dev->sector_pos); + num, dev->sector_pos); ret = scsi_cdrom_read_data(dev, msf, type, flags, dev->vendor_type); From 48c294a13bdd59abadd7f3271e49601c5a2ce39a Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Mar 2025 20:59:18 +0100 Subject: [PATCH 046/158] SCSI CD-ROM: Fix a warning. --- src/scsi/scsi_cdrom.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index a8bb1513b..b35662eeb 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -1096,8 +1096,10 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev) int msf = 0; int type = dev->sector_type; int flags = dev->sector_flags; +#ifdef ENABLE_SCSI_CDROM_LOG int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ? dev->requested_blocks : 1; +#endif switch (dev->current_cdb[0]) { case GPCMD_READ_CD_MSF_OLD: From be2a435e0510e939056a4334dfe5293d336f3cae Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 00:43:49 +0100 Subject: [PATCH 047/158] MO and ZIP: Fix reading, writing, and formatting, also fix > 2 GB MO images. --- src/disk/mo.c | 34 +++++++++++++++++++--------------- src/disk/zip.c | 17 +++++++++-------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index 7808e524e..b470b7761 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -63,7 +63,7 @@ const uint8_t mo_command_flags[0x100] = { [0x0a] = IMPLEMENTED | CHECK_READY, [0x0b] = IMPLEMENTED | CHECK_READY, [0x12] = IMPLEMENTED | ALLOW_UA, - [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x13] = IMPLEMENTED | CHECK_READY, [0x15] = IMPLEMENTED, [0x16] = IMPLEMENTED | SCSI_ONLY, [0x17] = IMPLEMENTED | SCSI_ONLY, @@ -74,8 +74,7 @@ const uint8_t mo_command_flags[0x100] = { [0x25] = IMPLEMENTED | CHECK_READY, [0x28] = IMPLEMENTED | CHECK_READY, [0x2a ... 0x2c] = IMPLEMENTED | CHECK_READY, - [0x2e] = IMPLEMENTED | CHECK_READY, - [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x2e ... 0x2f] = IMPLEMENTED | CHECK_READY, [0x41] = IMPLEMENTED | CHECK_READY, [0x55] = IMPLEMENTED, [0x5a] = IMPLEMENTED, @@ -172,9 +171,9 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert) } if (ret) { - fseek(dev->drv->fp, 0, SEEK_END); + fseeko64(dev->drv->fp, 0, SEEK_END); - uint32_t size = (uint32_t) ftell(dev->drv->fp); + uint64_t size = (uint64_t) ftello64(dev->drv->fp); unsigned int found = 0; if (is_mdi) { @@ -185,7 +184,7 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert) dev->drv->base = 0; for (uint8_t i = 0; i < KNOWN_MO_TYPES; i++) { - if (size == (mo_types[i].sectors * mo_types[i].bytes_per_sector)) { + if (size == ((uint64_t) mo_types[i].sectors * mo_types[i].bytes_per_sector)) { found = 1; dev->drv->medium_size = mo_types[i].sectors; dev->drv->sector_size = mo_types[i].bytes_per_sector; @@ -194,7 +193,7 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert) } if (found) { - if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1) + if (fseeko64(dev->drv->fp, (uint64_t) dev->drv->base, SEEK_SET) == -1) log_fatal(dev->log, "mo_load(): Error seeking to the beginning of " "the file\n"); @@ -799,21 +798,21 @@ mo_blocks(mo_t *dev, int32_t *len, int out) *len = 0; - if (!dev->sector_len) - mo_command_complete(dev); - else { + if (dev->sector_len == 0) { mo_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { mo_log(dev->log, "Trying to %s beyond the end of disk\n", out ? "write" : "read"); mo_lba_out_of_range(dev); + ret = 0; } else { *len = dev->requested_blocks * dev->drv->sector_size; ret = 1; for (int i = 0; i < dev->requested_blocks; i++) { - if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size) + (i * dev->drv->sector_size), SEEK_SET) == -1) { + if (fseeko64(dev->drv->fp, dev->drv->base + + ((uint64_t) dev->sector_pos * dev->drv->sector_size), SEEK_SET) == -1) { if (out) mo_write_error(dev); else @@ -854,6 +853,9 @@ mo_blocks(mo_t *dev, int32_t *len, int out) dev->sector_len -= dev->requested_blocks; } } + } else { + mo_command_complete(dev); + ret = 0; } return ret; @@ -888,7 +890,7 @@ mo_format(mo_t *dev) mo_log(dev->log, "Formatting media...\n"); - fseek(dev->drv->fp, 0, SEEK_END); + fseeko64(dev->drv->fp, 0, SEEK_END); long size = ftell(dev->drv->fp); #ifdef _WIN32 @@ -962,8 +964,9 @@ mo_erase(mo_t *dev) mo_buf_alloc(dev, dev->drv->sector_size); memset(dev->buffer, 0, dev->drv->sector_size); - fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size), - SEEK_SET); + fseeko64(dev->drv->fp, dev->drv->base + + ((uint64_t) dev->sector_pos * dev->drv->sector_size), + SEEK_SET); for (i = 0; i < dev->requested_blocks; i++) { if (feof(dev->drv->fp)) @@ -1878,7 +1881,8 @@ mo_phase_data_out(scsi_common_t *sc) dev->buffer[6] = (s >> 8) & 0xff; dev->buffer[7] = s & 0xff; } - if (fseek(dev->drv->fp, (i * dev->drv->sector_size), SEEK_SET) == -1) + if (fseeko64(dev->drv->fp, + ((uint64_t) i * dev->drv->sector_size), SEEK_SET) == -1) mo_write_error(dev); if (feof(dev->drv->fp)) break; diff --git a/src/disk/zip.c b/src/disk/zip.c index f579f23ec..ae3319b40 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -53,7 +53,7 @@ const uint8_t zip_command_flags[0x100] = { [0x0c] = IMPLEMENTED, [0x0d] = IMPLEMENTED | ATAPI_ONLY, [0x12] = IMPLEMENTED | ALLOW_UA, - [0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x13] = IMPLEMENTED | CHECK_READY, [0x15] = IMPLEMENTED, [0x16 ... 0x17] = IMPLEMENTED | SCSI_ONLY, [0x1a] = IMPLEMENTED, @@ -64,8 +64,7 @@ const uint8_t zip_command_flags[0x100] = { [0x25] = IMPLEMENTED | CHECK_READY, [0x28] = IMPLEMENTED | CHECK_READY, [0x2a ... 0x2b] = IMPLEMENTED | CHECK_READY, - [0x2e] = IMPLEMENTED | CHECK_READY, - [0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [0x2e ... 0x2f] = IMPLEMENTED | CHECK_READY, [0x41] = IMPLEMENTED | CHECK_READY, [0x55] = IMPLEMENTED, [0x5a] = IMPLEMENTED, @@ -898,9 +897,7 @@ zip_blocks(zip_t *dev, int32_t *len, const int out) int ret = 1; *len = 0; - if (!dev->sector_len) - zip_command_complete(dev); - else { + if (dev->sector_len > 0) { zip_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); @@ -908,12 +905,13 @@ zip_blocks(zip_t *dev, int32_t *len, const int out) zip_log(dev->log, "Trying to %s beyond the end of disk\n", out ? "write" : "read"); zip_lba_out_of_range(dev); + ret = 0; } else { *len = dev->requested_blocks << 9; for (int i = 0; i < dev->requested_blocks; i++) { - if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos << 9) + - (i << 9), SEEK_SET) == -1) { + if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos << 9), + SEEK_SET) == -1) { if (out) zip_write_error(dev); else @@ -952,6 +950,9 @@ zip_blocks(zip_t *dev, int32_t *len, const int out) dev->sector_len -= dev->requested_blocks; } } + } else { + zip_command_complete(dev); + ret = 0; } return ret; From 6f8594f2b22504027d4471e146d296d7a32944f2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 01:38:59 +0100 Subject: [PATCH 048/158] MO: A few bug fixes. --- src/disk/mo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index b470b7761..3165a805e 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -798,7 +798,7 @@ mo_blocks(mo_t *dev, int32_t *len, int out) *len = 0; - if (dev->sector_len == 0) { + if (dev->sector_len > 0) { mo_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); @@ -891,7 +891,7 @@ mo_format(mo_t *dev) mo_log(dev->log, "Formatting media...\n"); fseeko64(dev->drv->fp, 0, SEEK_END); - long size = ftell(dev->drv->fp); + int64_t size = ftello64(dev->drv->fp); #ifdef _WIN32 LARGE_INTEGER liSize; From 1a6f84d455287b56232c3b7a0366616f531a3648 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 03:00:56 +0100 Subject: [PATCH 049/158] MO: More bug fixes. --- src/disk/mo.c | 56 +++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index 3165a805e..e2db4bda3 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -17,6 +17,7 @@ * Copyright 2020-2025 Miran Grca. * Copyright 2020-2025 Fred N. van Kempen */ +#define _GNU_SOURCE #ifdef ENABLE_MO_LOG #include #endif @@ -432,7 +433,8 @@ mo_update_request_length(mo_t *dev, int len, int block_len) case 0xa8: case 0xaa: /* Round it to the nearest 2048 bytes. */ - dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + dev->max_transfer_len = (dev->max_transfer_len / dev->drv->sector_size) * + dev->drv->sector_size; /* Make sure total length is not bigger than sum of the lengths of @@ -792,10 +794,9 @@ mo_invalid_field_pl(mo_t *dev, const uint32_t field) } static int -mo_blocks(mo_t *dev, int32_t *len, int out) +mo_blocks(mo_t *dev, int32_t *len, const int out) { - int ret = 0; - + int ret = 1; *len = 0; if (dev->sector_len > 0) { @@ -803,41 +804,39 @@ mo_blocks(mo_t *dev, int32_t *len, int out) dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { - mo_log(dev->log, "Trying to %s beyond the end of disk\n", out ? "write" : "read"); + mo_log(dev->log, "Trying to %s beyond the end of disk\n", + out ? "write" : "read"); mo_lba_out_of_range(dev); - ret = 0; + ret = 0; } else { - *len = dev->requested_blocks * dev->drv->sector_size; - ret = 1; + *len = dev->requested_blocks * dev->drv->sector_size; for (int i = 0; i < dev->requested_blocks; i++) { - if (fseeko64(dev->drv->fp, dev->drv->base + - ((uint64_t) dev->sector_pos * dev->drv->sector_size), SEEK_SET) == -1) { + if (fseeko64(dev->drv->fp, (uint64_t) dev->drv->base + + (uint64_t) (dev->sector_pos * dev->drv->sector_size), + SEEK_SET) == -1) { if (out) mo_write_error(dev); else mo_read_error(dev); - ret = -1; } else { - if (!feof(dev->drv->fp)) + if (feof(dev->drv->fp)) break; if (out) { if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1, - dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) { + dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) { mo_log(dev->log, "mo_blocks(): Error writing data\n"); mo_write_error(dev); ret = -1; } else fflush(dev->drv->fp); - } else { - if (fread(dev->buffer + (i * dev->drv->sector_size), 1, - dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) { - mo_log(dev->log, "mo_blocks(): Error reading data\n"); - mo_read_error(dev); - ret = -1; - } + } else if (fread(dev->buffer + (i * dev->drv->sector_size), 1, + dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) { + mo_log(dev->log, "mo_blocks(): Error reading data\n"); + mo_read_error(dev); + ret = -1; } } @@ -848,7 +847,8 @@ mo_blocks(mo_t *dev, int32_t *len, int out) } if (ret == 1) { - mo_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + mo_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : + "Read", *len); dev->sector_len -= dev->requested_blocks; } @@ -1394,7 +1394,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = 512; + alloc_length = dev->drv->sector_size; switch (cdb[0]) { case GPCMD_VERIFY_6: @@ -1444,11 +1444,11 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_buf_alloc(dev, dev->packet_len); dev->requested_blocks = max_len; - dev->packet_len = max_len << 9; + dev->packet_len = max_len * dev->drv->sector_size; mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - mo_data_command_finish(dev, dev->packet_len, 512, + mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size, dev->packet_len, 1); ui_sb_update_icon(SB_MO | dev->id, @@ -1465,7 +1465,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) case GPCMD_WRITE_SAME_10: mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - alloc_length = 512; + alloc_length = dev->drv->sector_size; if ((cdb[1] & 6) == 6) mo_invalid_field(dev, cdb[1]); @@ -1484,7 +1484,8 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_set_phase(dev, SCSI_PHASE_DATA_OUT); - mo_data_command_finish(dev, 512, 512, + mo_data_command_finish(dev, dev->drv->sector_size, + dev->drv->sector_size, alloc_length, 1); ui_sb_update_icon(SB_MO | dev->id, @@ -1916,6 +1917,9 @@ mo_phase_data_out(scsi_common_t *sc) block_desc_len = 0; pos = hdr_len + block_desc_len; + mo_log(dev->log, "Block descriptor: %08X %08X %08X %08X %08X %08X %08X %08X\n", + dev->buffer[hdr_len], dev->buffer[hdr_len + 1], dev->buffer[hdr_len + 2], dev->buffer[hdr_len + 3], + dev->buffer[hdr_len + 4], dev->buffer[hdr_len + 5], dev->buffer[hdr_len + 6], dev->buffer[hdr_len + 7]); while (1) { if (pos >= param_list_len) { From 39f65003dc999c2716bc9cfddde3b760b8d42ae6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 03:32:47 +0100 Subject: [PATCH 050/158] Acer 100T: Do not add a separate internal FDC because one is already provided by the Super I/O chip, fixes #5250. --- src/machine/m_at_286_386sx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 9086f7c8a..fd9cc3bcd 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -750,9 +750,6 @@ machine_at_acer100t_init(const machine_t *model) machine_at_ps2_ide_init(model); - if (fdc_current[0] == FDC_INTERNAL) - device_add(&fdc_at_device); - device_add(&ali1409_device); if (gfxcard[0] == VID_INTERNAL) device_add(&oti077_acer100t_device); From 8eb084d397aa8033494e69f4fcf18605fd64ae2f Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 03:34:49 +0100 Subject: [PATCH 051/158] XT KBC: Fix switches for 192k RAM, fixes #5262. --- src/device/keyboard_xt.c | 64 ++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index ddbcae61b..3c616a2ab 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -84,6 +84,7 @@ typedef struct xtkbd_t { uint8_t key_waiting; uint8_t type; uint8_t pravetz_flags; + uint8_t cpu_speed; pc_timer_t send_delay_timer; } xtkbd_t; @@ -799,6 +800,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) kbd_adddata(0xaa); } } + kbd->pb = val; if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI)) kbd->clock = !!(kbd->pb & 0x40); @@ -846,6 +848,14 @@ kbd_write(uint16_t port, uint8_t val, void *priv) } break; + case 0x1f0: + kbd_log("XTkbd: Port %04X out: %02X\n", port, val); + if (kbd->type == KBD_TYPE_VTECH) { + kbd->cpu_speed = val; + cpu_dynamic_switch(kbd->cpu_speed >> 7); + } + break; + default: break; } @@ -863,12 +873,14 @@ kbd_read(uint16_t port, void *priv) (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI))) { + (kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI) || + (kbd->type == KBD_TYPE_VTECH))) { if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI)) ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00); - else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86)) + else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || + (kbd->type == KBD_TYPE_VTECH)) /* According to Ruud on the PCem forum, this is supposed to return 0xFF on the XT. */ ret = 0xff; @@ -926,16 +938,8 @@ kbd_read(uint16_t port, void *priv) } else { if (kbd->pb & 0x08) /* PB3 */ ret = kbd->pd >> 4; - else { - /* LaserXT = Always 512k RAM; - LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ -#ifdef USE_LASERXT - if (kbd->type == KBD_TYPE_VTECH) - ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00); - else -#endif /* USE_LASERXT */ - ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); - } + else + ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); } ret |= (ppispeakon ? 0x20 : 0); @@ -956,7 +960,8 @@ kbd_read(uint16_t port, void *priv) case 0x63: /* Keyboard Configuration Register (aka Port D) */ if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || - (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI)) + (kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI) || + (kbd->type == KBD_TYPE_VTECH)) ret = kbd->pd; break; @@ -966,6 +971,12 @@ kbd_read(uint16_t port, void *priv) kbd_log("XTkbd: Port %02X in : %02X\n", port, ret); break; + case 0x1f0: + if (kbd->type == KBD_TYPE_VTECH) + ret = kbd->cpu_speed; + kbd_log("XTkbd: Port %04X in : %02X\n", port, ret); + break; + default: break; } @@ -984,7 +995,7 @@ kbd_reset(void *priv) kbd->pb = 0x00; kbd->pravetz_flags = 0x00; - keyboard_scan = 1; + keyboard_scan = 1; key_queue_start = 0; key_queue_end = 0; @@ -1006,12 +1017,16 @@ kbd_init(const device_t *info) io_sethandler(0x0060, 4, kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); keyboard_send = kbd_adddata_ex; - kbd_reset(kbd); kbd->type = info->local; - if (kbd->type == KBD_TYPE_PRAVETZ) { + if (kbd->type == KBD_TYPE_VTECH) + kbd->cpu_speed = (!!cpu) << 2; + kbd_reset(kbd); + if (kbd->type == KBD_TYPE_PRAVETZ) io_sethandler(0x00c0, 16, kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); - } + if (kbd->type == KBD_TYPE_VTECH) + io_sethandler(0x01f0, 1, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); key_queue_start = key_queue_end = 0; @@ -1021,7 +1036,8 @@ kbd_init(const device_t *info) (kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) || (kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) || - (kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI)) { + (kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI) || + (kbd->type == KBD_TYPE_VTECH)) { /* DIP switch readout: bit set = OFF, clear = ON. */ if (kbd->type == KBD_TYPE_OLIVETTI) /* Olivetti M19 @@ -1035,7 +1051,7 @@ kbd_init(const device_t *info) /* Switches 7, 8 - floppy drives. */ kbd->pd = get_fdd_switch_settings(); - /* Siitches 5, 6 - video card type */ + /* Switches 5, 6 - video card type */ kbd->pd |= get_videomode_switch_settings(); /* Switches 3, 4 - memory size. */ @@ -1057,7 +1073,7 @@ kbd_init(const device_t *info) kbd->pd |= 0x0c; break; } - } else if (kbd->type == KBD_TYPE_XT82) { + } else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_VTECH)) { switch (mem_size) { case 64: /* 1x64k */ kbd->pd |= 0x00; @@ -1075,9 +1091,13 @@ kbd_init(const device_t *info) } } else if (kbd->type == KBD_TYPE_PC82) { switch (mem_size) { +#ifdef PC82_192K_3BANK case 192: /* 3x64k, not supported by stock BIOS due to bugs */ kbd->pd |= 0x08; break; +#else + case 192: /* 2x64k + 2x32k */ +#endif case 64: /* 4x16k */ case 96: /* 2x32k + 2x16k */ case 128: /* 4x32k */ @@ -1294,8 +1314,8 @@ const device_t keyboard_xt_t1x00_device = { #ifdef USE_LASERXT const device_t keyboard_xt_lxt3_device = { - .name = "VTech Laser XT3 Keyboard", - .internal_name = "keyboard_xt_lxt3", + .name = "VTech Laser Turbo XT Keyboard", + .internal_name = "keyboard_xt_lxt", .flags = 0, .local = KBD_TYPE_VTECH, .init = kbd_init, From 25bcd434a0936f96875126758f510c84bc53a541 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 18 Mar 2025 13:06:14 +0600 Subject: [PATCH 052/158] Qt: Add special handling for real touchscreen devices --- src/qt/qt_renderercommon.cpp | 4 +++ src/qt/qt_rendererstack.cpp | 65 ++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_renderercommon.cpp b/src/qt/qt_renderercommon.cpp index 178134c9d..2a20ff63c 100644 --- a/src/qt/qt_renderercommon.cpp +++ b/src/qt/qt_renderercommon.cpp @@ -144,6 +144,10 @@ RendererCommon::eventDelegate(QEvent *event, bool &result) case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + case QEvent::TouchUpdate: case QEvent::Wheel: case QEvent::Enter: case QEvent::Leave: diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 2b1cfdf26..8c0792be4 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -38,6 +38,7 @@ #include #include +#include #ifdef __APPLE__ # include @@ -63,6 +64,7 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index) : QStackedWidget(parent) , ui(new Ui::RendererStack) { + setAttribute(Qt::WA_AcceptTouchEvents, true); rendererTakesScreenshots = false; #ifdef Q_OS_WINDOWS int raw = 1; @@ -477,8 +479,8 @@ RendererStack::event(QEvent* event) if (m_monitor_index >= 1) { if (mouse_input_mode >= 1) { - mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); - mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + mouse_x_abs = (mouse_event->localPos().x()) / (double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); if (!mouse_tablet_in_proximity) mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; } @@ -487,15 +489,66 @@ RendererStack::event(QEvent* event) #ifdef Q_OS_WINDOWS if (mouse_input_mode == 0) { - mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); - mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + mouse_x_abs = (mouse_event->localPos().x()) / (double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); return QStackedWidget::event(event); } #endif - mouse_x_abs = (mouse_event->localPos().x()) / (long double)width(); - mouse_y_abs = (mouse_event->localPos().y()) / (long double)height(); + mouse_x_abs = (mouse_event->localPos().x()) / (double)width(); + mouse_y_abs = (mouse_event->localPos().y()) / (double)height(); mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity; + } else switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QTouchEvent* touchevent = (QTouchEvent*)event; + if (mouse_input_mode == 0) break; + if (touchevent->touchPoints().count()) { + mouse_x_abs = (touchevent->touchPoints()[0].pos().x()) / (double)width(); + mouse_y_abs = (touchevent->touchPoints()[0].pos().y()) / (double)height(); + } + mouse_set_buttons_ex(mouse_get_buttons_ex() | 1); + touchevent->accept(); + return true; +#else + QTouchEvent* touchevent = (QTouchEvent*)event; + if (mouse_input_mode == 0) break; + if (touchevent->pointCount()) { + mouse_x_abs = (touchevent->point(0).position().x()) / (double)width(); + mouse_y_abs = (touchevent->point(0).position().y()) / (double)height(); + } + mouse_set_buttons_ex(mouse_get_buttons_ex() | 1); + touchevent->accept(); + return true; +#endif + } + case QEvent::TouchEnd: + case QEvent::TouchCancel: + { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QTouchEvent* touchevent = (QTouchEvent*)event; + if (mouse_input_mode == 0) break; + if (touchevent->touchPoints().count()) { + mouse_x_abs = (touchevent->touchPoints()[0].pos().x()) / (double)width(); + mouse_y_abs = (touchevent->touchPoints()[0].pos().y()) / (double)height(); + } + mouse_set_buttons_ex(mouse_get_buttons_ex() & ~1); + touchevent->accept(); + return true; +#else + QTouchEvent* touchevent = (QTouchEvent*)event; + if (mouse_input_mode == 0) break; + if (touchevent->pointCount()) { + mouse_x_abs = (touchevent->point(0).position().x()) / (double)width(); + mouse_y_abs = (touchevent->point(0).position().y()) / (double)height(); + } + mouse_set_buttons_ex(mouse_get_buttons_ex() & ~1); + touchevent->accept(); + return true; +#endif + } } return QStackedWidget::event(event); From 96644d137f785cec857b9a1c217dae65d563d50b Mon Sep 17 00:00:00 2001 From: rushieda <185547947+rushieda@users.noreply.github.com> Date: Tue, 18 Mar 2025 19:57:14 +0300 Subject: [PATCH 053/158] Add the Soyo SY-7SBB (SiS 600, Socket 370) --- src/include/86box/machine.h | 1 + src/machine/m_at_socket370.c | 28 ++++++++++++++++++++++++ src/machine/machine_table.c | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index b2e4c01f2..d1257d94c 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -855,6 +855,7 @@ extern int machine_at_s1857_init(const machine_t *); extern int machine_at_p6bap_init(const machine_t *); extern int machine_at_p6bat_init(const machine_t *); extern int machine_at_prosignias31x_bx_init(const machine_t *); +extern int machine_at_7sbb_init(const machine_t *); /* m_at_misc.c */ extern int machine_at_vpc2007_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 9be2d45b8..b2e311166 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -541,3 +541,31 @@ machine_at_6via90ap_init(const machine_t *model) return ret; } + +int +machine_at_7sbb_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/7sbb/sbb12aa2.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); + device_add(&sis_5600_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&it8661f_device); + device_add(&sst_flash_29ee020_device); /* assumed */ + + return ret; +} \ No newline at end of file diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 3706126a3..bae9de29f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -16227,6 +16227,48 @@ const machine_t machines[] = { .snd_device = &cmi8738_onboard_device, .net_device = NULL }, + /* SiS (5)600 */ + /* Has the SiS 600 chipset, which is a re-brand of the 5600, with + on-chip KBC. */ + { + .name = "[SiS 600] Soyo SY-7SBB", + .internal_name = "7sbb", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_SIS_5600, + .init = machine_at_7sbb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK(CPU_CYRIX3S), + .min_bus = 60000000, + .max_bus = 100000000, + .min_voltage = 1800, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 1572864, + .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 = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Miscellaneous/Fake/Hypervisor machines */ /* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC From aaaa96f785ca2ecdfa9b76561e074b6ea4815323 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 18:20:49 +0100 Subject: [PATCH 054/158] QT render stack: add a missing default entry. Also committing the missing MO image creation fixes. --- src/qt/qt_newfloppydialog.cpp | 18 +++++++++--------- src/qt/qt_rendererstack.cpp | 3 +++ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/qt/qt_newfloppydialog.cpp b/src/qt/qt_newfloppydialog.cpp index 48be09777..58a7a3df2 100644 --- a/src/qt/qt_newfloppydialog.cpp +++ b/src/qt/qt_newfloppydialog.cpp @@ -367,7 +367,7 @@ NewFloppyDialog::create86f(const QString &filename, const disk_size_t &disk_size bool NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type) { - uint32_t total_size = 0; + uint64_t total_size = 0; uint32_t total_sectors = 0; uint32_t sector_bytes = 0; uint32_t root_dir_bytes = 0; @@ -388,7 +388,7 @@ NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t &d total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) total_sectors = ZIP_250_SECTORS; - total_size = total_sectors * sector_bytes; + total_size = (uint64_t) total_sectors * sector_bytes; root_dir_bytes = (disk_size.root_dir_entries << 5); fat_size = (disk_size.spfat * sector_bytes); fat1_offs = sector_bytes; @@ -465,11 +465,11 @@ NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t &d bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type, QProgressDialog &pbar) { - uint32_t total_size = 0; + uint64_t total_size = 0; uint32_t total_sectors = 0; uint32_t sector_bytes = 0; uint16_t base = 0x1000; - uint32_t pbar_max = 0; + uint64_t pbar_max = 0; QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { @@ -482,7 +482,7 @@ NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_size_t total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; if (total_sectors > ZIP_SECTORS) total_sectors = ZIP_250_SECTORS; - total_size = total_sectors * sector_bytes; + total_size = (uint64_t) total_sectors * sector_bytes; pbar_max = total_size; if (type == FileType::Zdi) { @@ -649,12 +649,12 @@ bool NewFloppyDialog::createMoSectorImage(const QString &filename, int8_t disk_size, FileType type, QProgressDialog &pbar) { const mo_type_t *dp = &mo_types[disk_size]; - uint32_t total_size = 0; - uint32_t total_size2; + uint64_t total_size = 0; + uint64_t total_size2; uint32_t total_sectors = 0; uint32_t sector_bytes = 0; uint16_t base = 0x1000; - uint32_t pbar_max = 0; + uint64_t pbar_max = 0; uint32_t blocks_num; QFile file(filename); @@ -666,7 +666,7 @@ NewFloppyDialog::createMoSectorImage(const QString &filename, int8_t disk_size, sector_bytes = dp->bytes_per_sector; total_sectors = dp->sectors; - total_size = total_sectors * sector_bytes; + total_size = (uint64_t) total_sectors * sector_bytes; total_size2 = (total_size >> 20) << 20; total_size2 = total_size - total_size2; diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 8c0792be4..3e81a52c2 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -549,6 +549,9 @@ RendererStack::event(QEvent* event) return true; #endif } + + default: + return QStackedWidget::event(event); } return QStackedWidget::event(event); From 70dcdee72bbedc8fe138edaf4321e7145c22f2f1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 19:21:00 +0100 Subject: [PATCH 055/158] Some Cyrix MII table/ID fixes and added some Cyrix CPU blocking for the NuPRO 592 and the P5MMS98. --- src/cpu/cpu.c | 8 ++++ src/cpu/cpu_table.c | 89 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b821bc657..0c621bf68 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -384,6 +384,14 @@ cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine) if (cpu_override) return 1; + /* Cyrix 6x86MX on the NuPRO 592. */ + if (((cpu_s->cyrix_id & 0xff00) == 0x0400) && (strstr(machine_s->internal_name, "nupro") != NULL)) + return 0; + + /* Cyrix 6x86MX or MII on the P5MMS98. */ + if ((cpu_s->cpu_type == CPU_Cx6x86MX) && (strstr(machine_s->internal_name, "p5mms98") != NULL)) + return 0; + /* Check CPU blocklist. */ if (machine_s->cpu.block) { i = 0; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 5a156853e..e5c91b1a8 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -6366,6 +6366,74 @@ const cpu_family_t cpu_families[] = { .name = "MII", .internal_name = "mii", .cpus = (const CPU[]) { + { + .name = "IBM 133 (PR166)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0851, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "166 (PR200)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0852, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "187.5 (PR233)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 187500000, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0852, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 45/2 + }, + { + .name = "208.3 (PR266)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 208333333, + .multi = 2.5, + .voltage = 2700, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0852, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 17, + .mem_write_cycles = 17, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 25 + }, { .name = "233 (PR300)", .cpu_type = CPU_Cx6x86MX, @@ -6375,7 +6443,7 @@ const cpu_family_t cpu_families[] = { .voltage = 2900, .edx_reset = 0x601, .cpuid_model = 0x601, - .cyrix_id = 0x0852, + .cyrix_id = 0x0854, .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, .mem_read_cycles = 21, .mem_write_cycles = 21, @@ -6409,7 +6477,7 @@ const cpu_family_t cpu_families[] = { .voltage = 2900, .edx_reset = 0x601, .cpuid_model = 0x601, - .cyrix_id = 0x0853, + .cyrix_id = 0x0852, .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, .mem_read_cycles = 23, .mem_write_cycles = 23, @@ -6417,6 +6485,23 @@ const cpu_family_t cpu_families[] = { .cache_write_cycles = 7, .atclk_div = 30 }, + { + .name = "270 (PR350)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 270000000, + .multi = 3.0, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0853, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 25, + .mem_write_cycles = 25, + .cache_read_cycles = 8, + .cache_write_cycles = 8, + .atclk_div = 32 + }, { .name = "285 (PR400)", .cpu_type = CPU_Cx6x86MX, From 66b99cc2ff27dd9a9d962d4dc7ae1ad9a95efe09 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 22:49:03 +0100 Subject: [PATCH 056/158] QT render stack: ignore the wheel event on Windows and Apple. --- src/qt/qt_rendererstack.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 3e81a52c2..5b464f6a5 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -203,6 +203,9 @@ RendererStack::mousePressEvent(QMouseEvent *event) void RendererStack::wheelEvent(QWheelEvent *event) { +#if defined(Q_OS_WINDOWS) || defined(__APPLE__) + event->ignore(); +#else if (!mouse_capture) { event->ignore(); return; @@ -212,6 +215,7 @@ RendererStack::wheelEvent(QWheelEvent *event) mouse_set_z((int) numSteps); event->accept(); +#endif } void From 9bce2496be920bb3d2b260b53e17044d79205e0c Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 18 Mar 2025 22:51:19 +0100 Subject: [PATCH 057/158] Corrected the behavior of that. --- src/qt/qt_rendererstack.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 5b464f6a5..5dc61e03b 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -203,19 +203,17 @@ RendererStack::mousePressEvent(QMouseEvent *event) void RendererStack::wheelEvent(QWheelEvent *event) { -#if defined(Q_OS_WINDOWS) || defined(__APPLE__) - event->ignore(); -#else if (!mouse_capture) { event->ignore(); return; } +#if !defined(Q_OS_WINDOWS) && !defined(__APPLE__) double numSteps = (double) event->angleDelta().y() / 120.0; mouse_set_z((int) numSteps); - event->accept(); #endif + event->accept(); } void From 67f0e9574098eab70590cae94059bdf40878f3e0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Mar 2025 00:24:13 +0100 Subject: [PATCH 058/158] Fixed an off by 1 error in the new recompiler. --- src/codegen_new/codegen_backend_x86-64_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index 39173505b..c70112c86 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -533,7 +533,7 @@ host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data) codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/ codegen_addword(block, imm_data); } else if (offset < (1ULL << 32)) { - codegen_alloc_bytes(block, 8); + codegen_alloc_bytes(block, 9); codegen_addbyte3(block, 0x66, 0xc7, 0x85); /*MOV offset[RBP], imm_data*/ codegen_addlong(block, offset); codegen_addword(block, imm_data); From f05e2f34b615d879e7a60216ab8d24961087a023 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Mar 2025 08:51:52 +0900 Subject: [PATCH 059/158] added JEGA video emulation --- src/include/86box/vid_ega.h | 21 ++ src/video/CMakeLists.txt | 1 + src/video/vid_ega.c | 26 +- src/video/vid_jega.c | 724 ++++++++++++++++++++++++++++++++++++ src/video/vid_table.c | 1 + 5 files changed, 757 insertions(+), 16 deletions(-) create mode 100644 src/video/vid_jega.c diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 0bccd607e..082cb120a 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -140,6 +140,11 @@ typedef struct ega_t { uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); void (*render)(struct ega_t *svga); + + /*If set then another device is driving the monitor output and the EGA + card should not attempt to display anything */ + void (*render_override)(void *priv); + void *priv_parent; } ega_t; #endif @@ -150,6 +155,7 @@ extern const device_t sega_device; extern const device_t atiega800p_device; extern const device_t iskra_ega_device; extern const device_t et2000_device; +extern const device_t jega_device; #endif extern int update_overscan; @@ -199,4 +205,19 @@ void ega_render_text(ega_t *ega); void ega_render_graphics(ega_t *ega); #endif +enum { + EGA_IBM = 0, + EGA_COMPAQ, + EGA_SUPEREGA, + EGA_ATI800P, + EGA_ISKRA, + EGA_TSENG +}; + +enum { + EGA_TYPE_IBM = 0, + EGA_TYPE_OTHER = 1, + EGA_TYPE_COMPAQ = 2 +}; + #endif /*VIDEO_EGA_H*/ diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index fdd94f6c6..062fc272a 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -78,6 +78,7 @@ add_library(vid OBJECT vid_xga.c vid_bochs_vbe.c vid_ps55da2.c + vid_jega.c nv/nv_rivatimer.c ) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 10df85c79..781e9a9dd 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -45,21 +45,6 @@ void ega_doblit(int wx, int wy, ega_t *ega); #define BIOS_ISKRA_PATH "roms/video/ega/143-02.bin", "roms/video/ega/143-03.bin" #define BIOS_TSENG_PATH "roms/video/ega/EGA ET2000.BIN" -enum { - EGA_IBM = 0, - EGA_COMPAQ, - EGA_SUPEREGA, - EGA_ATI800P, - EGA_ISKRA, - EGA_TSENG -}; - -enum { - EGA_TYPE_IBM = 0, - EGA_TYPE_OTHER = 1, - EGA_TYPE_COMPAQ = 2 -}; - static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static uint8_t ega_rotate[8][256]; static int active = 0; @@ -107,6 +92,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) case 0x3c0: case 0x3c1: + if (ega->actual_type == EGA_SUPEREGA) + val &= 0x7f; /* Bit 7 indicates the flipflop status (read only) */ if (!ega->attrff) { ega->attraddr = val & 31; if ((val & 0x20) != ega->attr_palette_enable) { @@ -325,6 +312,8 @@ ega_in(uint16_t addr, void *priv) case 0x3c0: if (ega_type == EGA_TYPE_OTHER) ret = ega->attraddr | ega->attr_palette_enable; + if (ega->actual_type == EGA_SUPEREGA && ega->attrff) + ret |= 0x80; /* Bit 7 indicates the flipflop status (read only) */ break; case 0x3c1: if (ega_type == EGA_TYPE_OTHER) @@ -754,7 +743,10 @@ ega_poll(void *priv) ega->y_add *= ega->vres + 1; for (y = 0; y <= ega->vres; y++) { /* Render scanline */ - ega->render(ega); + if(ega->render_override) + ega->render_override(ega->priv_parent); + else + ega->render(ega); /* Render overscan */ ega->x_add = (overscan_x >> 1); @@ -1429,6 +1421,8 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) ega->crtc[0] = 63; ega->crtc[6] = 255; + ega->render_override = NULL; + timer_add(&ega->timer, ega_poll, ega, 1); if (ega_type == EGA_TYPE_COMPAQ) timer_add(&ega->dot_timer, ega_dot_poll, ega, 1); diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c new file mode 100644 index 000000000..ad312faff --- /dev/null +++ b/src/video/vid_jega.c @@ -0,0 +1,724 @@ +/* + * 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. + * + * Emulation of the JEGA (Japanese EGA), a part of the AX architecture. + * + * It's an extension of the SuperEGA. Superimposing text (AX-2) is not available. + * + * Authors: Akamaki + * + * Copyright 2025 Akamaki + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/pic.h> +#include <86box/pit.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/device.h> +#include <86box/video.h> +#include <86box/vid_ega.h> + +/* JEGA internal registers */ +#define RPESL 0x09 /* End Scan Line */ +#define RCCSL 0x0A /* Cursor Start Line */ +#define RCCEL 0x0B /* Cursor End Line */ +#define RCCLH 0x0E /* Cursor Location High */ +#define RCCLL 0x0F /* Cursor Location Low */ +#define RPULP 0x14 /* Under Line Position */ +/* + 0xB8 - 0x20 */ +#define RMOD1 0x21 /* Display out, EGA through, Superimpose, Sync with EGA, Master EGA, Slave EGA, n/a, Test */ +#define RMOD2 0x22 /* 1st Attr, 2nd Attr, Blink/Int, n/a, Font access mode (b3-2), Font map sel (b1-0)*/ +#define RDAGS 0x23 /* ANK Group Select */ +#define RDFFB 0x24 /* Font Access First Byte */ +#define RDFSB 0x25 /* Font Access Second Byte */ +#define RDFAP 0x26 /* Font Access Pattern */ +#define RSTAT 0x27 /* Font Status Register */ +/* + 0xD0 - 0x20 */ +#define RPSSU 0x29 /* Start Scan Upper */ +#define RPSSL 0x2A /* Start Scan Lower */ +#define RPSSC 0x2B /* Start Scan Count */ +#define RPPAJ 0x2C /* Phase Adjust Count */ +#define RCMOD 0x2D /* Cursor Mode */ +#define RCSKW 0x2E /* Cursor Skew Control */ +#define ROMSL 0x2F /* ? */ +#define RINVALID_INDEX 0x30 + +#define JEGA_PATH_BIOS "roms/video/jega/OKI_IF386AX_VBIOS.bin" +#define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" +#define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ +#define DBCS16_CHARS 0x2c10 +#define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2) + +#define INVALIDACCESS8 0xffu +#define INVALIDACCESS16 0xffffu +#define INVALIDACCESS32 0xffffffffu + +#ifndef RELEASE_BUILD +// # define ENABLE_JEGA_LOG 1 +#endif + +#ifdef ENABLE_JEGA_LOG +int jega_do_log = ENABLE_JEGA_LOG; + +static void +jega_log(const char *fmt, ...) +{ + va_list ap; + + if (jega_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define jega_log(fmt, ...) +#endif + +static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; + +typedef struct jega_t { + rom_t bios_rom; + ega_t ega; + uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */ + uint8_t regs[0x31]; + uint8_t egapal[16]; + uint8_t attrregs[32]; + uint8_t attraddr; + uint8_t attrff; + uint8_t attr_palette_enable; + uint32_t *pallook; + int con; + int cursoron; + int cursorblink_disable; + int ca; + int font_index; + int sbcsbank_inv; + int attr3_sbcsbank; + int start_scan_lower; + int start_scan_upper; + int start_scan_count; + uint8_t *vram; + uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */ + uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */ +} jega_t; + +static void jega_recalctimings(void *priv); + +#define FONTX_LEN_ID 6 +#define FONTX_LEN_FN 8 + +typedef struct { + char id[FONTX_LEN_ID]; + char name[FONTX_LEN_FN]; + unsigned char width; + unsigned char height; + unsigned char type; +} fontx_h; + +typedef struct { + uint16_t start; + uint16_t end; +} fontx_tbl; + +static uint32_t pallook64[256]; +static bool is_SJIS_1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } +static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } + +static uint16_t +SJIS_to_SEQ(uint16_t sjis) +{ + uint32_t chr1 = (sjis >> 8) & 0xff; + uint32_t chr2 = sjis & 0xff; + if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) return INVALIDACCESS16; + chr1 -= 0x81; + if (chr1 > 0x5E) chr1 -= 0x40; + chr2 -= 0x40; + if (chr2 > 0x3F) chr2--; + chr1 *= 0xBC; + return (chr1 + chr2); +} + +static uint8_t +dbcs_read(uint16_t sjis, int index, void *priv) { + jega_t *jega = (jega_t *) priv; + int seq = SJIS_to_SEQ(sjis); + if (seq >= DBCS16_CHARS || index >= 32) + return INVALIDACCESS8; + return jega->jfont_dbcs_16[seq * 32 + index]; +} + +static void +dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) { + jega_t *jega = (jega_t *) priv; + int seq = SJIS_to_SEQ(sjis); + if (seq >= DBCS16_CHARS || index >= 32) + return; + jega->jfont_dbcs_16[seq * 32 + index] = val; +} + +/* Display Adapter Mode 3 Drawing */ +void +jega_render_text(void *priv) +{ + jega_t *jega = (jega_t *) priv; + if (jega->ega.firstline_draw == 2000) + jega->ega.firstline_draw = jega->ega.displine; + jega->ega.lastline_draw = jega->ega.displine; + + if (jega->ega.fullchange) { + // const bool doublewidth = ((jega->ega.seqregs[1] & 8) != 0); + const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ + // const bool attrlinechars = (jega->ega.attrregs[0x10] & 4); + const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || (jega->regs[RMOD1] & 0x80 == 0); + const int charwidth = 8; + const bool blinked = jega->ega.blink & 0x10; + uint32_t *p = &buffer32->line[jega->ega.displine + jega->ega.y_add][jega->ega.x_add]; + bool chr_wide = false; + int sc_wide = jega->ega.sc - jega->start_scan_count; + const bool cursoron = (blinked || jega->cursorblink_disable) + && (jega->ega.sc >= jega->regs[RCCSL]) && (jega->ega.sc <= jega->regs[RCCEL]); + uint32_t chr_first; + uint32_t attr_basic; + int fg; + int bg; + + for (int x = 0; x < (jega->ega.hdisp + jega->ega.scrollcache); x += charwidth) { + uint32_t addr = jega->ega.remap_func(&jega->ega, jega->ega.ma) & jega->ega.vrammask; + + int drawcursor = ((jega->ega.ma == jega->ca) && cursoron); + + uint32_t chr; + uint32_t attr; + if (!crtcreset) { + chr = jega->ega.vram[addr]; + attr = jega->ega.vram[addr + 1]; + } else + chr = attr = 0; + if (chr_wide) { + uint8_t attr_ext = 0; + /* the code may be in DBCS */ + if (jega->regs[RMOD2] & 0x40) { + /* Parse JEGA extended attribute */ + /* Bold | 2x width | 2x height | U/L select | R/L select | - | - | - */ + attr_ext = attr; + if ((attr_ext & 0x30) == 0x30) + sc_wide = jega->ega.sc - jega->start_scan_lower; /* Set top padding of lower 2x character */ + else if ((attr_ext & 0x30) == 0x20) + sc_wide = jega->ega.sc - jega->start_scan_upper; /* Set top padding of upper 2x character */ + else + sc_wide = jega->ega.sc - jega->start_scan_count; + } + if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && jega->ega.sc <= jega->regs[RPESL]) { + chr_first <<= 8; + chr |= chr_first; + /* Vertical wide font (Extended Attribute) */ + if (attr_ext & 0x20) { + if (attr_ext & 0x10) + sc_wide = (sc_wide >> 1) + 8; + else + sc_wide = sc_wide >> 1; + } + /* Horizontal wide font (Extended Attribute) */ + if (attr_ext & 0x40) { + uint32_t dat = dbcs_read(chr, sc_wide, jega); + if (!(attr_ext & 0x08)) { /* right half of character */ + dat = dbcs_read(chr, sc_wide + 16, jega); + } + for (int xx = 0; xx < charwidth; xx++) { + p[xx * 2] = (dat & (0x80 >> xx)) ? fg : bg; + p[xx * 2 + 1] = (dat & (0x80 >> xx)) ? fg : bg; + } + } else { + uint32_t dat = dbcs_read(chr, sc_wide, jega); + dat <<= 8; + dat |= dbcs_read(chr, sc_wide + 16, jega); + /* Bold (Extended Attribute) */ + if (attr_ext &= 0x80) { + uint32_t dat2 = dat; + dat2 >>= 1; + dat |= dat2; + } + for (int xx = 0; xx < charwidth * 2; xx++) + p[xx] = (dat & (0x8000 >> xx)) ? fg : bg; + } + } else { + /* invalid DBCS code or line space then put blank */ + for (int xx = 0; xx < charwidth * 2; xx++) + p[xx] = bg; + } + if (attr_basic & 0x20) { /* vertical line */ + p[0] = fg; + } + if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + for (int xx = 0; xx < charwidth * 2; xx++) + p[xx] = fg; + } + chr_wide = false; + p += (charwidth * 2); + } else { + /* SBCS or invalid second byte of DBCS */ + if (jega->regs[RMOD2] & 0x80) { + /* Parse attribute as JEGA */ + /* Blink | Reverse | V line | U line | (Bit 3-0 is the same as EGA) */ + /* The background color is always black (transparent in AX-2) */ + if (drawcursor || attr & 0x40) { + bg = jega->pallook[jega->egapal[attr & 0x0f]]; + fg = 0; + } else { + fg = jega->pallook[jega->egapal[attr & 0x0f]]; + bg = 0; + if (attr & 0x80) { + bg = 0; + if (blinked) + fg = bg; + } + } + attr_basic = attr; + } else { + /* Parse attribute as EGA */ + /* BInt/Blink | BR | BG | BB | Int/Group | R | G | B */ + if (drawcursor) { + bg = jega->pallook[jega->egapal[attr & 0x0f]]; + fg = jega->pallook[jega->egapal[attr >> 4]]; + } else { + fg = jega->pallook[jega->egapal[attr & 0x0f]]; + bg = jega->pallook[jega->egapal[attr >> 4]]; + if ((attr & 0x80) && attrblink) { + bg = jega->pallook[jega->egapal[(attr >> 4) & 7]]; + if (blinked) + fg = bg; + } + } + attr_basic = 0; + } + + if (is_SJIS_1(chr)) { + /* the char code maybe in DBCS */ + chr_first = chr; + chr_wide = true; + } else { + /* the char code is in SBCS */ + uint32_t charaddr = chr; + // if (jega->attr3_sbcsbank && (attr & 8)) + // charaddr |= 0x100; + // if (jega->sbcsbank_inv) + // charaddr ^= 0x100; + charaddr *= 19; + + uint32_t dat = jega->jfont_sbcs_19[charaddr + jega->ega.sc]; + for (int xx = 0; xx < charwidth; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + + if (attr_basic & 0x20) { /* vertical line */ + p[0] = fg; + } + if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + for (int xx = 0; xx < charwidth; xx++) + p[xx] = fg; + } + p += charwidth; + } + } + jega->ega.ma += 4; + } + jega->ega.ma &= 0x3ffff; + } +} + +static void +jega_out(uint16_t addr, uint8_t val, void *priv) +{ + uint8_t o; + jega_t *jega = (jega_t *) priv; + // jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc); + switch (addr) { + case 0x3c0: + case 0x3c1: + jega_log("Palette %02X %02X(%d) %04X:%04X\n", jega->attraddr, val, val, cs >> 4, cpu_state.pc); + /* Palette (write only) */ + if (!jega->attrff) { + jega->attraddr = val & 31; + if ((val & 0x20) != jega->attr_palette_enable) { + jega->ega.fullchange = 3; + jega->attr_palette_enable = val & 0x20; + jega_recalctimings(jega); + } + } else { + o = jega->attrregs[jega->attraddr & 31]; + jega->attrregs[jega->attraddr & 31] = val; + if (jega->attraddr < 0x10) { + for (uint8_t c = 0; c < 16; c++) { + jega->egapal[c] = jega->attrregs[c] & 0x3f; + } + jega->ega.fullchange = changeframecount; + } + } + jega->attrff ^= 1; + break; + case 0x3b4: + case 0x3d4: + /* Index 0x00-0x1F (write only), 0xB8-0xDF (write and read) */ + if (val >= 0xB8 && val <= 0xBF) + jega->regs_index = val - 0xB8 + 0x20; + else if (val >= 0xD8 && val <= 0xDF) + jega->regs_index = val - 0xD0 + 0x20; + else if (val <= 0x1F) + jega->regs_index = val; + else + jega->regs_index = RINVALID_INDEX; + break; + case 0x3b5: + case 0x3d5: + /* Data */ + if (jega->regs_index != RINVALID_INDEX) { + jega->regs[jega->regs_index] = val; + jega_log("JEGA Out %04X(%02X) %02Xh(%d) %04X:%04X\n", addr, jega->regs_index, val, val, cs >> 4, cpu_state.pc); + switch (jega->regs_index) { + case RMOD1: + /* if the value is changed */ + // if (jega->regs[jega->regs_index] != val) { + if (val & 0x40) + jega->ega.render_override = NULL; + else + jega->ega.render_override = jega_render_text; + // } + break; + case RDAGS: + switch (val & 0x03) { + case 0x00: + jega->attr3_sbcsbank = false; + jega->sbcsbank_inv = false; + break; + case 0x01: + jega->attr3_sbcsbank = true; + jega->sbcsbank_inv = false; + break; + case 0x02: + jega->attr3_sbcsbank = true; + jega->sbcsbank_inv = true; + break; + case 0x03: + jega->attr3_sbcsbank = false; + jega->sbcsbank_inv = true; + break; + } + break; + case RCCLH: + case RCCLL: + jega->ca = jega->regs[RCCLH] << 10 | jega->regs[RCCLL] << 2; + break; + case RCMOD: + jega->cursoron = (val & 0x80); + jega->cursorblink_disable = (~val & 0x20); + break; + case RDFFB: + case RDFSB: + /* reset the line number */ + jega->font_index = 0; + break; + case RPSSC: + if (val <= 17) + jega->start_scan_count = val + 1; + else + jega->start_scan_count = (val - 32) + 1; + break; + case RPSSL: + jega->start_scan_lower = val - 15; + break; + case RPSSU: + if (val <= 33) + jega->start_scan_upper = val + 4; + else + jega->start_scan_upper = (val - 64) + 4; + break; + case RDFAP: + uint16_t chr = jega->regs[RDFFB]; + if (is_SJIS_1(chr) && chr >= 0xf0 && chr <= 0xf3) { + chr <<= 8; + chr |= jega->regs[RDFSB]; + if (jega->font_index < 32) + dbcs_write(chr, jega->font_index, val, jega); + } else { + if (jega->font_index <19) + jega->jfont_sbcs_19[chr * 19 + jega->font_index] = val; + } + jega_log("JEGA Font W %X %d %02Xh(%d) %04X:%04X\n", chr, jega->font_index, val, val, cs >> 4, cpu_state.pc); + jega->font_index++; + break; + } + } + break; + default: + break; + } + if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ + ega_out(addr, val, &jega->ega); +} + +static uint8_t +jega_in(uint16_t addr, void *priv) +{ + jega_t *jega = (jega_t *) priv; + uint8_t ret = INVALIDACCESS8; + switch (addr) { + case 0x3b5: + case 0x3d5: + if (jega->regs_index >= 0x20 && jega->regs_index <= 0x2F) { + switch (jega->regs_index) { + case RDFAP: + uint16_t chr = jega->regs[RDFFB]; + /* DBCS or SBCS */ + if (is_SJIS_1(chr)) { + chr <<= 8; + chr |= jega->regs[RDFSB]; + if (jega->font_index < 32) + ret = dbcs_read(chr, jega->font_index, jega); + } else { + if (jega->font_index < 19) + ret = jega->jfont_sbcs_19[chr * 19 + jega->font_index]; + } + jega_log("JEGA Font R %X %d %02Xh(%d) %04X:%04X\n", chr, jega->font_index, ret, ret, cs >> 4, cpu_state.pc); + jega->font_index++; + break; + case RSTAT: + ret = 0x03; + break; + default: + ret = jega->regs[jega->regs_index]; + break; + } + jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); + } else if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ + ret = ega_in(addr, &jega->ega); + break; + case 0x3ba: + case 0x3da: + jega->attrff = 0; + default: + if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave is redirected to Master in AX-1. */ + ret = ega_in(addr, &jega->ega); + break; + } + // jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); + return ret; +} + +static int +getfontx2header(FILE *fp, fontx_h *header) +{ + fread(header->id, FONTX_LEN_ID, 1, fp); + if (strncmp(header->id, "FONTX2", FONTX_LEN_ID) != 0) { + return 1; + } + fread(header->name, FONTX_LEN_FN, 1, fp); + header->width = (uint8_t) getc(fp); + header->height = (uint8_t) getc(fp); + header->type = (uint8_t) getc(fp); + return 0; +} + +static uint16_t +chrtosht(FILE *fp) +{ + uint16_t i, j; + i = (uint16_t) getc(fp); + j = (uint16_t) getc(fp) << 8; + return (i | j); +} + +static void +readfontxtbl(fontx_tbl *table, int size, FILE *fp) +{ + while (size > 0) { + table->start = chrtosht(fp); + table->end = chrtosht(fp); + ++table; + --size; + } +} + +static int +LoadFontxFile(const char *fn, void *priv) +{ + fontx_h fhead; + fontx_tbl *ftbl; + uint16_t code; + uint16_t scode; + uint8_t size; + uint8_t buf; + int line; + jega_t *jega = (jega_t *) priv; + FILE *fp = rom_fopen(fn, "rb"); + jega_log("JEGA: Loading font\n"); + if (fp == NULL) { + jega_log("JEGA: font file '%s' not found.\n", fn); + return 0; + } + if (getfontx2header(fp, &fhead) != 0) { + fclose(fp); + jega_log("JEGA: FONTX2 header is incorrect.\n"); + return 1; + } + /* DBCS or SBCS */ + if (fhead.type == 1) { + if (fhead.width == 16 && fhead.height == 16) { + size = getc(fp); + ftbl = (fontx_tbl *) calloc(size, sizeof(fontx_tbl)); + readfontxtbl(ftbl, size, fp); + for (int i = 0; i < size; i++) { + for (code = ftbl[i].start; code <= ftbl[i].end; code++) { + scode = SJIS_to_SEQ(code); + if (scode != INVALIDACCESS16) { + for (line = 0; line < 16; line++) { + fread(&buf, sizeof(uint8_t), 1, fp); + jega->jfont_dbcs_16[(int) (scode * 32) + line] = buf; + fread(&buf, sizeof(uint8_t), 1, fp); + jega->jfont_dbcs_16[(int) (scode * 32) + line + 16] = buf; + } + } else { + fseek(fp, 32, SEEK_CUR); + } + } + } + } else { + fclose(fp); + jega_log("JEGA: Width or height of DBCS font doesn't match.\n"); + return 1; + } + } else { + if (fhead.width == 8 && fhead.height == 19) { + fread(jega->jfont_sbcs_19, sizeof(uint8_t), SBCS19_FILESIZE, fp); + } else { + fclose(fp); + jega_log("JEGA: Width or height of SBCS font doesn't match.\n"); + return 1; + } + } + fclose(fp); + return 0; +} + +static void * +jega_init(const device_t *info) +{ + jega_t *jega = calloc(1, sizeof(jega_t)); + + rom_init(&jega->bios_rom, JEGA_PATH_BIOS, 0xc0000, 0x8000, 0x7fff, 0, 0); + memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); + LoadFontxFile(JEGA_PATH_FONTDBCS, jega); + + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + } + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + jega->pallook = pallook64; + ega_init(&jega->ega, 9, 0); + jega->ega.actual_type = EGA_SUPEREGA; + jega->ega.priv_parent = jega; + mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); + + io_sethandler(0x03b0, 0x0030, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + + jega->regs[RMOD1] = 0x48; +} + +static void +jega_close(void *priv) +{ + jega_t *jega = (jega_t *) priv; +#ifdef ENABLE_JEGA_LOG + FILE *f; + // f = fopen("jega_font16.dmp", "wb"); + // if (f != NULL) { + // fwrite(jega->jfont_dbcs_16, DBCS16_FILESIZE, 1, f); + // fclose(f); + // } + // f = fopen("jega_font19.dmp", "wb"); + // if (f != NULL) { + // fwrite(jega->jfont_sbcs_19, SBCS19_FILESIZE, 1, f); + // fclose(f); + // } + f = fopen("jega_regs.txt", "wb"); + if (f != NULL) { + for (int i = 0; i < 49; i++) + fprintf(f, "Regs %02X: %4X\n", i, jega->regs[i]); + for (int i = 0; i < 32; i++) + fprintf(f, "Attr %02X: %4X\n", i, jega->attrregs[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]); + for (int i = 0; i < 64; i++) + fprintf(f, "RealPal %02X: %4X\n", i, jega->pallook[i]); + fclose(f); + } + // f = fopen("ega_vram.dmp", "wb"); + // if (f != NULL) { + // fwrite(jega->ega.vram, 256 * 1024, 1, f); + // fclose(f); + // } + f = fopen("ram_bda.dmp", "wb"); + if (f != NULL) { + fwrite(&ram[0x0], 0x500, 1, f); + fclose(f); + } + // jega_log("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); +#endif + if (jega->ega.eeprom) + free(jega->ega.eeprom); + free(jega->ega.vram); + free(jega); +} + +static void +jega_recalctimings(void *priv) +{ + jega_t *jega = (jega_t *) priv; + ega_recalctimings(&jega->ega); +} +static void +jega_speed_changed(void *priv) +{ + jega_t *jega = (jega_t *) priv; + + jega_recalctimings(jega); +} + +static int +jega_available(void) +{ + return (rom_present(JEGA_PATH_BIOS) && rom_present(JEGA_PATH_FONTDBCS)); +} + +const device_t jega_device = { + .name = "JEGA", + .internal_name = "jega", + .flags = DEVICE_ISA, + .local = 0, + .init = jega_init, + .close = jega_close, + .reset = NULL, + .available = jega_available, + .speed_changed = jega_speed_changed, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d1df2ba20..be26d9e18 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -68,6 +68,7 @@ video_cards[] = { { .device = &ati18800_wonder_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &cga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &sega_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &jega_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5401_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5402_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5420_isa_device, .flags = VIDEO_FLAG_TYPE_NONE }, From 4d3e2a3be35606bce7d70275053ef18730c10e42 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Mar 2025 10:38:17 +0900 Subject: [PATCH 060/158] changed rom filename --- src/video/vid_jega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index ad312faff..b6695893c 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -59,7 +59,7 @@ #define ROMSL 0x2F /* ? */ #define RINVALID_INDEX 0x30 -#define JEGA_PATH_BIOS "roms/video/jega/OKI_IF386AX_VBIOS.bin" +#define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 From 395f23cf57d608b561f6cdde77d2976e602328b0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Mar 2025 03:12:36 +0100 Subject: [PATCH 061/158] More Cyrix fixes. --- src/cpu/386_common.c | 60 +++++++--- src/cpu/cpu.c | 236 ++++++++++++++++++++++++++-------------- src/cpu/cpu.h | 7 ++ src/cpu/x86_ops_cyrix.h | 208 ++++++++++++++++++++++++++++++----- 4 files changed, 383 insertions(+), 128 deletions(-) diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index 5b0e1a5c4..2853e3c9a 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -1449,26 +1449,44 @@ enter_smm(int in_hlt) void enter_smm_check(int in_hlt) { - if ((in_smm == 0) && smi_line) { -#ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while not in SMM\n"); -#endif - enter_smm(in_hlt); - } else if ((in_smm == 1) && smi_line) { - /* Mark this so that we don't latch more than one SMI. */ -#ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while in unlatched SMM\n"); -#endif - smi_latched = 1; - } else if ((in_smm == 2) && smi_line) { - /* Mark this so that we don't latch more than one SMI. */ -#ifdef ENABLE_386_COMMON_LOG - x386_common_log("SMI while in latched SMM\n"); -#endif - } + uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && (cyrix.arr[3].size > 0); + + if (smi_line) { + if (!is_cxsmm || ccr1_check) switch (in_smm) { + default: +#ifdef ENABLE_386_COMMON_LOG + fatal("SMI while in_smm = %i\n", in_smm); + break; +#endif + case 0: +#ifdef ENABLE_386_COMMON_LOG + x386_common_log("SMI while not in SMM\n"); +#endif + enter_smm(in_hlt); + break; + case 1: + /* Mark this so that we don't latch more than one SMI. */ +#ifdef ENABLE_386_COMMON_LOG + x386_common_log("SMI while in unlatched SMM\n"); +#endif + smi_latched = 1; + break; + case 2: +#ifdef ENABLE_386_COMMON_LOG + x386_common_log("SMI while in latched SMM\n"); +#endif + break; + } +#ifdef ENABLE_386_COMMON_LOG + else { + x386_common_log("SMI while in Cyrix disabled mode\n"); + x386_common_log("lol\n"); + } +#endif - if (smi_line) smi_line = 0; + } } void @@ -2186,6 +2204,12 @@ cpu_fast_off_reset(void) void smi_raise(void) { + uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && (cyrix.arr[3].size > 0); + + if (is_cxsmm && !ccr1_check) + return; + if (is486 && (cpu_fast_off_flags & 0x80000000)) cpu_fast_off_advance(); diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 0c621bf68..41ca6932d 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -40,6 +40,7 @@ #include <86box/nmi.h> #include <86box/pic.h> #include <86box/pci.h> +#include <86box/smram.h> #include <86box/timer.h> #include <86box/gdbstub.h> #include <86box/plat_fallthrough.h> @@ -50,13 +51,6 @@ #endif /* USE_DYNAREC */ #include "x87_timings.h" -#define CCR1_USE_SMI (1 << 1) -#define CCR1_SMAC (1 << 2) -#define CCR1_SM3 (1 << 7) - -#define CCR3_SMI_LOCK (1 << 0) -#define CCR3_NMI_EN (1 << 1) - enum { CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */ CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */ @@ -289,6 +283,10 @@ uint8_t ccr5; uint8_t ccr6; uint8_t ccr7; +uint8_t reg_30 = 0x00; +uint8_t arr[24] = { 0 }; +uint8_t rcr[8] = { 0 }; + static int cyrix_addr; static void cpu_write(uint16_t addr, uint8_t val, void *priv); @@ -2627,6 +2625,23 @@ cpu_ven_reset(void) msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; break; + case CPU_Cx6x86MX: + ccr0 = 0x00; + ccr1 = 0x00; + ccr2 = 0x00; + ccr3 = 0x00; + ccr4 = 0x80; + ccr5 = 0x00; + ccr6 = 0x00; + memset(arr, 0x00, 24); + memset(rcr, 0x00, 3); + cyrix.arr[3].base = 0x00; + cyrix.arr[3].size = 0; /* Disabled */ + cyrix.smhr &= ~SMHR_VALID; + CPUID = cpu_s->cpuid_model; + reg_30 = 0xff; + break; + case CPU_PENTIUMPRO: case CPU_PENTIUM2: case CPU_PENTIUM2D: @@ -4237,78 +4252,105 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) picintc(1 << 13); else nmi = 0; - return; - } else if (addr >= 0xf1) - return; /* FPU stuff */ - - if (!(addr & 1)) + } else if ((addr < 0xf1) && !(addr & 1)) cyrix_addr = val; - else - switch (cyrix_addr) { - case 0xc0: /* CCR0 */ - ccr0 = val; - break; - case 0xc1: /* CCR1 */ - if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) - val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); - ccr1 = val; - break; - case 0xc2: /* CCR2 */ - ccr2 = val; - break; - case 0xc3: /* CCR3 */ - if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) - val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; - ccr3 = val; - break; - case 0xcd: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); - cyrix.smhr &= ~SMHR_VALID; - } - break; - case 0xce: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); - cyrix.smhr &= ~SMHR_VALID; - } - break; - case 0xcf: - if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) { - cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); - if ((val & 0xf) == 0xf) - cyrix.arr[3].size = 1ULL << 32; /* 4 GB */ - else if (val & 0xf) - cyrix.arr[3].size = 2048 << (val & 0xf); - else - cyrix.arr[3].size = 0; /* Disabled */ - cyrix.smhr &= ~SMHR_VALID; - } - break; + else if (addr < 0xf1) switch (cyrix_addr) { + default: + if (cyrix_addr >= 0xc0) + fatal("Writing unimplemented Cyrix register %02X\n", cyrix_addr); + break; - case 0xe8: /* CCR4 */ - if ((ccr3 & 0xf0) == 0x10) { - ccr4 = val; - if (cpu_s->cpu_type >= CPU_Cx6x86) { - if (val & 0x80) - CPUID = cpu_s->cpuid_model; - else - CPUID = 0; - } + case 0x30: /* ???? */ + reg_30 = val; + break; + + case 0xc0: /* CCR0 */ + ccr0 = val; + break; + case 0xc1: { /* CCR1 */ + uint8_t old = ccr1; + if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) + val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); + ccr1 = val; + if ((old ^ ccr1) & (CCR1_SMAC)) { + if (ccr1 & CCR1_SMAC) + smram_backup_all(); + smram_recalc_all(!(ccr1 & CCR1_SMAC)); + } + break; + } case 0xc2: /* CCR2 */ + ccr2 = val; + break; + case 0xc3: /* CCR3 */ + if ((ccr3 & CCR3_SMI_LOCK) && !in_smm) + val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; + ccr3 = val; + break; + + case 0xc4 ... 0xcc: + if (ccr5 & 0x20) + arr[cyrix_addr - 0xc4] = val; + break; + case 0xcd: + if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) { + arr[cyrix_addr - 0xc4] = val; + cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xce: + if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) { + arr[cyrix_addr - 0xc4] = val; + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xcf: + if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) { + arr[cyrix_addr - 0xc4] = val; + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); + if ((val & 0xf) == 0xf) + cyrix.arr[3].size = 1ULL << 32; /* 4 GB */ + else if (val & 0xf) + cyrix.arr[3].size = 2048 << (val & 0xf); + else + cyrix.arr[3].size = 0; /* Disabled */ + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xd0 ... 0xdb: + if (((ccr3 & 0xf0) == 0x10) && (ccr5 & 0x20)) + arr[cyrix_addr - 0xc4] = val; + break; + + case 0xdc ... 0xe3: + if ((ccr3 & 0xf0) == 0x10) + rcr[cyrix_addr - 0xdc] = val; + break; + + case 0xe8: /* CCR4 */ + if ((ccr3 & 0xf0) == 0x10) { + ccr4 = val; + if (cpu_s->cpu_type >= CPU_Cx6x86) { + if (val & 0x80) + CPUID = cpu_s->cpuid_model; + else + CPUID = 0; } - break; - case 0xe9: /* CCR5 */ - if ((ccr3 & 0xf0) == 0x10) - ccr5 = val; - break; - case 0xea: /* CCR6 */ - if ((ccr3 & 0xf0) == 0x10) - ccr6 = val; - break; - case 0xeb: /* CCR7 */ - ccr7 = val & 5; - break; - } + } + break; + case 0xe9: /* CCR5 */ + if ((ccr3 & 0xf0) == 0x10) + ccr5 = val; + break; + case 0xea: /* CCR6 */ + if ((ccr3 & 0xf0) == 0x10) + ccr6 = val; + break; + case 0xeb: /* CCR7 */ + ccr7 = val & 5; + break; + } } static uint8_t @@ -4319,6 +4361,15 @@ cpu_read(uint16_t addr, UNUSED(void *priv)) if (addr == 0xf007) ret = 0x7f; else if ((addr < 0xf0) && (addr & 1)) switch (cyrix_addr) { + default: + if (cyrix_addr >= 0xc0) + fatal("Reading unimplemented Cyrix register %02X\n", cyrix_addr); + break; + + case 0x30: /* ???? */ + ret = reg_30; + break; + case 0xc0: ret = ccr0; break; @@ -4331,14 +4382,36 @@ cpu_read(uint16_t addr, UNUSED(void *priv)) case 0xc3: ret = ccr3; break; + + case 0xc4 ... 0xcc: + if (ccr5 & 0x20) + ret = arr[cyrix_addr - 0xc4]; + break; + case 0xcd ... 0xcf: + if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) + ret = arr[cyrix_addr - 0xc4]; + break; + case 0xd0 ... 0xdb: + if (((ccr3 & 0xf0) == 0x10) && (ccr5 & 0x20)) + ret = arr[cyrix_addr - 0xc4]; + break; + + case 0xdc ... 0xe3: + if ((ccr3 & 0xf0) == 0x10) + ret = rcr[cyrix_addr - 0xdc]; + break; + case 0xe8: - ret = ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; + if ((ccr3 & 0xf0) == 0x10) + ret = ccr4; break; case 0xe9: - ret = ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; + if ((ccr3 & 0xf0) == 0x10) + ret = ccr5; break; case 0xea: - ret = ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; + if ((ccr3 & 0xf0) == 0x10) + ret = ccr6; break; case 0xeb: ret = ccr7; @@ -4349,11 +4422,8 @@ cpu_read(uint16_t addr, UNUSED(void *priv)) case 0xff: ret = cpu_s->cyrix_id >> 8; break; - - default: - break; } - + return ret; } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index d58da6998..80097294d 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -120,6 +120,13 @@ enum { #define CPU_ALTERNATE_XTAL 4 #define CPU_FIXED_MULTIPLIER 8 +#define CCR1_USE_SMI (1 << 1) +#define CCR1_SMAC (1 << 2) +#define CCR1_SM3 (1 << 7) + +#define CCR3_SMI_LOCK (1 << 0) +#define CCR3_NMI_EN (1 << 1) + #if (defined __amd64__ || defined _M_X64) # define LOOKUP_INV -1LL #else diff --git a/src/cpu/x86_ops_cyrix.h b/src/cpu/x86_ops_cyrix.h index ac864cd20..c95d4b038 100644 --- a/src/cpu/x86_ops_cyrix.h +++ b/src/cpu/x86_ops_cyrix.h @@ -35,7 +35,13 @@ opSVDC_common(uint32_t fetchdat) static int opSVDC_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); opSVDC_common(fetchdat); @@ -47,7 +53,13 @@ opSVDC_a16(uint32_t fetchdat) static int opSVDC_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); opSVDC_common(fetchdat); @@ -88,7 +100,13 @@ opRSDC_common(uint32_t fetchdat) static int opRSDC_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); opRSDC_common(fetchdat); @@ -100,7 +118,13 @@ opRSDC_a16(uint32_t fetchdat) static int opRSDC_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); opRSDC_common(fetchdat); @@ -113,7 +137,13 @@ opRSDC_a32(uint32_t fetchdat) static int opSVLDT_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); @@ -126,7 +156,13 @@ opSVLDT_a16(uint32_t fetchdat) static int opSVLDT_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); @@ -140,7 +176,13 @@ opSVLDT_a32(uint32_t fetchdat) static int opRSLDT_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); @@ -152,7 +194,13 @@ opRSLDT_a16(uint32_t fetchdat) static int opRSLDT_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt); @@ -165,7 +213,13 @@ opRSLDT_a32(uint32_t fetchdat) static int opSVTS_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); @@ -178,7 +232,13 @@ opSVTS_a16(uint32_t fetchdat) static int opSVTS_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); @@ -192,7 +252,13 @@ opSVTS_a32(uint32_t fetchdat) static int opRSTS_a16(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); @@ -205,7 +271,13 @@ opRSTS_a16(uint32_t fetchdat) static int opRSTS_a32(uint32_t fetchdat) { - if (in_smm) { + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr); @@ -219,9 +291,13 @@ opRSTS_a32(uint32_t fetchdat) static int opSMINT(UNUSED(uint32_t fetchdat)) { + uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) && + (cyrix.arr[3].size > 0); + if (in_smm) fatal("opSMINT\n"); - else { + else if (ccr1_check) { is_smint = 1; enter_smm(0); } @@ -232,9 +308,26 @@ opSMINT(UNUSED(uint32_t fetchdat)) static int opRDSHR_a16(UNUSED(uint32_t fetchdat)) { - if (in_smm) - fatal("opRDSHR_a16\n"); - else + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].l = cyrix.smhr; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(cyrix.smhr); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 0); + } + return cpu_state.abrt; + } else x86illegal(); return 1; @@ -242,30 +335,91 @@ opRDSHR_a16(UNUSED(uint32_t fetchdat)) static int opRDSHR_a32(UNUSED(uint32_t fetchdat)) { - if (in_smm) - fatal("opRDSHR_a32\n"); - else + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cpu_state.regs[cpu_rm].l = cyrix.smhr; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteal(cyrix.smhr); + CLOCK_CYCLES(is486 ? 1 : 2); + PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 1); + } + return cpu_state.abrt; + } else x86illegal(); return 1; } static int -opWRSHR_a16(UNUSED(uint32_t fetchdat)) +opWRSHR_a16(uint32_t fetchdat) { - if (in_smm) - fatal("opWRSHR_a16\n"); - else + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { + fetch_ea_16(fetchdat); + if (cpu_mod == 3) { + cyrix.smhr = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0); + } else { + uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + temp = geteal(); + if (cpu_state.abrt) + return 1; + cyrix.smhr = temp; + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 0); + } + return 0; + } else x86illegal(); return 1; } static int -opWRSHR_a32(UNUSED(uint32_t fetchdat)) +opWRSHR_a32(uint32_t fetchdat) { - if (in_smm) - fatal("opWRSHR_a32\n"); - else + uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) == + (CCR1_USE_SMI | CCR1_SM3)) && + ((ccr1 & CCR1_SMAC) || in_smm) && + (cyrix.arr[3].size > 0) && + (CPL == 0); + + if (ins_check) { + fetch_ea_32(fetchdat); + if (cpu_mod == 3) { + cyrix.smhr = cpu_state.regs[cpu_rm].l; + CLOCK_CYCLES(timing_rr); + PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1); + } else { + uint32_t temp; + SEG_CHECK_READ(cpu_state.ea_seg); + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + temp = geteal(); + if (cpu_state.abrt) + return 1; + cyrix.smhr = temp; + CLOCK_CYCLES(is486 ? 1 : 4); + PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 1); + } + return 0; + } else x86illegal(); return 1; From 0fd97c8427a252e4994476663846a8eb30a05640 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Mar 2025 04:35:47 +0100 Subject: [PATCH 062/158] MO: Fix medium size in various conditions and fix handling of unsupported media. --- src/disk/mo.c | 30 +++++++++++++++++++++++++----- src/include/86box/mo.h | 2 ++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index e2db4bda3..e5cbd9140 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -18,6 +18,7 @@ * Copyright 2020-2025 Fred N. van Kempen */ #define _GNU_SOURCE +#include #ifdef ENABLE_MO_LOG #include #endif @@ -184,11 +185,14 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert) } else dev->drv->base = 0; + dev->drv->supported = 0; + for (uint8_t i = 0; i < KNOWN_MO_TYPES; i++) { if (size == ((uint64_t) mo_types[i].sectors * mo_types[i].bytes_per_sector)) { found = 1; dev->drv->medium_size = mo_types[i].sectors; dev->drv->sector_size = mo_types[i].bytes_per_sector; + dev->drv->supported = mo_drive_types[dev->drv->type].supported_media[i]; break; } } @@ -803,7 +807,12 @@ mo_blocks(mo_t *dev, int32_t *len, const int out) mo_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); - if (dev->sector_pos >= dev->drv->medium_size) { + if (!dev->drv->supported) { + mo_log(dev->log, "Trying to %s an unsupported medium\n", + out ? "write" : "read"); + out ? mo_write_error(dev) : mo_read_error(dev); + ret = 0; + } else if (dev->sector_pos >= dev->drv->medium_size) { mo_log(dev->log, "Trying to %s beyond the end of disk\n", out ? "write" : "read"); mo_lba_out_of_range(dev); @@ -955,7 +964,11 @@ mo_erase(mo_t *dev) mo_log(dev->log, "Erasing %i blocks starting from %i...\n", dev->sector_len, dev->sector_pos); - if (dev->sector_pos >= dev->drv->medium_size) { + if (!dev->drv->supported) { + mo_log(dev->log, "Trying to erase an unsupported medium\n"); + mo_write_error(dev); + return 0; + } else if (dev->sector_pos >= dev->drv->medium_size) { mo_log(dev->log, "Trying to erase beyond the end of disk\n"); mo_lba_out_of_range(dev); return 0; @@ -1386,6 +1399,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_set_phase(dev, SCSI_PHASE_STATUS); mo_command_complete(dev); break; + } else if (!dev->drv->supported) { + mo_read_error(dev); + break; } fallthrough; case GPCMD_WRITE_6: @@ -1433,7 +1449,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) break; } - if (dev->sector_pos > (mo_types[dev->drv->type].sectors - 1)) + if (!dev->drv->supported) + mo_write_error(dev); + else if (dev->sector_pos >= dev->drv->medium_size) mo_lba_out_of_range(dev); else { if (dev->sector_len) { @@ -1473,7 +1491,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - if (dev->sector_pos > (mo_types[dev->drv->type].sectors - 1)) + if (!dev->drv->supported) + mo_write_error(dev); + else if (dev->sector_pos >= dev->drv->medium_size) mo_lba_out_of_range(dev); else if (dev->sector_len) { mo_buf_alloc(dev, alloc_length); @@ -1834,7 +1854,7 @@ static uint8_t mo_phase_data_out(scsi_common_t *sc) { mo_t * dev = (mo_t *) sc; - const uint32_t last_sector = mo_types[dev->drv->type].sectors - 1; + const uint32_t last_sector = dev->drv->medium_size - 1; int len = 0; uint8_t error = 0; uint32_t last_to_write; diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index e09515b10..f4e7e9809 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -122,6 +122,8 @@ typedef struct mo_drive_t { uint32_t medium_size; uint32_t base; uint16_t sector_size; + + int supported; } mo_drive_t; typedef struct mo_t { From 2cd99f0c705c9a40cbc4a11866c05c03b6704734 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Mar 2025 07:54:54 +0100 Subject: [PATCH 063/158] X86 segmentation: apparently, the CPU can execute a data segment in some cases, used by LINK and CodeView, fixes #5283. --- src/cpu/x86seg.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index 2a0601661..145752237 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -1334,6 +1334,12 @@ pmoderetf(int is32, uint16_t off) if (CPL == (seg & 0x0003)) { x86seg_log("RETF CPL = RPL %04X\n", segdat[2]); switch (segdat[2] & 0x1f00) { + case 0x1000: + case 0x1100: + case 0x1200: + case 0x1300: + /* Data segment, apparently valid when CPL is the same, used by MS LINK for DOS. */ + fallthrough; case 0x1800: case 0x1900: case 0x1a00: @@ -1384,6 +1390,12 @@ pmoderetf(int is32, uint16_t off) cycles -= timing_retf_pm; } else { switch (segdat[2] & 0x1f00) { + case 0x1000: + case 0x1100: + case 0x1200: + case 0x1300: + /* Data segment, apparently valid when CPL is the same, used by MS LINK for DOS. */ + fallthrough; case 0x1800: case 0x1900: case 0x1a00: @@ -1605,6 +1617,12 @@ pmodeint(int num, int soft) return; } switch (segdat2[2] & 0x1f00) { + case 0x1000: + case 0x1100: + case 0x1200: + case 0x1300: + /* Data segment, apparently valid when CPL is the same, used by MS CodeView for DOS. */ + fallthrough; case 0x1800: case 0x1900: case 0x1a00: @@ -1983,6 +2001,12 @@ pmodeiret(int is32) } switch (segdat[2] & 0x1f00) { + case 0x1000: + case 0x1100: + case 0x1200: + case 0x1300: + /* Data segment, apparently valid when CPL is the same, used by MS CodeView for DOS. */ + fallthrough; case 0x1800: case 0x1900: case 0x1a00: From 21bafa37a5aae28aeb63f0e2f2ad4c5a0720d2b1 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 20 Mar 2025 00:44:03 +0900 Subject: [PATCH 064/158] correct a compile error --- src/video/vid_jega.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index b6695893c..3ff13e85d 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -347,6 +347,7 @@ jega_out(uint16_t addr, uint8_t val, void *priv) { uint8_t o; jega_t *jega = (jega_t *) priv; + uint16_t chr; // jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc); switch (addr) { case 0x3c0: @@ -449,7 +450,7 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega->start_scan_upper = (val - 64) + 4; break; case RDFAP: - uint16_t chr = jega->regs[RDFFB]; + chr = jega->regs[RDFFB]; if (is_SJIS_1(chr) && chr >= 0xf0 && chr <= 0xf3) { chr <<= 8; chr |= jega->regs[RDFSB]; @@ -477,13 +478,14 @@ jega_in(uint16_t addr, void *priv) { jega_t *jega = (jega_t *) priv; uint8_t ret = INVALIDACCESS8; + uint16_t chr; switch (addr) { case 0x3b5: case 0x3d5: if (jega->regs_index >= 0x20 && jega->regs_index <= 0x2F) { switch (jega->regs_index) { case RDFAP: - uint16_t chr = jega->regs[RDFFB]; + chr = jega->regs[RDFFB]; /* DBCS or SBCS */ if (is_SJIS_1(chr)) { chr <<= 8; From e932bc940df7fcd0c0555f051f486d334e790aed Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Mar 2025 17:48:08 +0100 Subject: [PATCH 065/158] JEGA: Fix warnings. --- src/video/vid_jega.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 3ff13e85d..c410a15da 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -186,7 +186,7 @@ jega_render_text(void *priv) // const bool doublewidth = ((jega->ega.seqregs[1] & 8) != 0); const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ // const bool attrlinechars = (jega->ega.attrregs[0x10] & 4); - const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || (jega->regs[RMOD1] & 0x80 == 0); + const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0); const int charwidth = 8; const bool blinked = jega->ega.blink & 0x10; uint32_t *p = &buffer32->line[jega->ega.displine + jega->ega.y_add][jega->ega.x_add]; @@ -345,7 +345,6 @@ jega_render_text(void *priv) static void jega_out(uint16_t addr, uint8_t val, void *priv) { - uint8_t o; jega_t *jega = (jega_t *) priv; uint16_t chr; // jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc); @@ -362,7 +361,6 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega_recalctimings(jega); } } else { - o = jega->attrregs[jega->attraddr & 31]; jega->attrregs[jega->attraddr & 31] = val; if (jega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { @@ -641,6 +639,8 @@ jega_init(const device_t *info) io_sethandler(0x03b0, 0x0030, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); jega->regs[RMOD1] = 0x48; + + return jega; } static void From 00c97dac1ccdd362a6781eedf8ba657ae5634019 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 20 Mar 2025 00:56:13 +0600 Subject: [PATCH 066/158] Add "Five + 2 Wheels" option for horizontal wheel reporting --- src/device/mouse.c | 45 +++++++++++++++++++++++- src/device/mouse_ps2.c | 61 ++++++++++++++++++++++++--------- src/include/86box/mouse.h | 3 ++ src/qt/macos_event_filter.mm | 1 + src/qt/qt_rendererstack.cpp | 2 ++ src/qt/qt_winrawinputfilter.cpp | 7 ++++ 6 files changed, 102 insertions(+), 17 deletions(-) diff --git a/src/device/mouse.c b/src/device/mouse.c index f0446d781..f7d8c9861 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -106,6 +106,7 @@ static mouse_t mouse_devices[] = { static _Atomic double mouse_x; static _Atomic double mouse_y; static atomic_int mouse_z; +static atomic_int mouse_w; static atomic_int mouse_buttons; static int mouse_delta_b; @@ -156,6 +157,7 @@ mouse_clear_coords(void) mouse_clear_y(); mouse_z = 0; + mouse_w = 0; } void @@ -355,6 +357,14 @@ mouse_wheel_moved(void) return ret; } +int +mouse_hwheel_moved(void) +{ + int ret = !!(atomic_load(&mouse_w)); + + return ret; +} + int mouse_moved(void) { @@ -373,13 +383,14 @@ mouse_state_changed(void) int b; int b_mask = (1 << mouse_nbut) - 1; int wheel = (mouse_nbut >= 4); + int hwheel = (mouse_nbut >= 6); int ret; b = atomic_load(&mouse_buttons); mouse_delta_b = (b ^ mouse_old_b); mouse_old_b = b; - ret = mouse_moved() || ((atomic_load(&mouse_z) != 0) && wheel) || (mouse_delta_b & b_mask); + ret = mouse_moved() || ((atomic_load(&mouse_z) != 0) && wheel) || ((atomic_load(&mouse_w) != 0) && hwheel) || (mouse_delta_b & b_mask); return ret; } @@ -475,6 +486,18 @@ mouse_clear_z(void) atomic_store(&mouse_z, 0); } +void +mouse_set_w(int w) +{ + atomic_fetch_add(&mouse_w, w); +} + +void +mouse_clear_w(void) +{ + atomic_store(&mouse_w, 0); +} + void mouse_subtract_z(int *delta_z, int min, int max, int invert) { @@ -495,6 +518,26 @@ mouse_subtract_z(int *delta_z, int min, int max, int invert) atomic_store(&mouse_z, invert ? -real_z : real_z); } +void +mouse_subtract_w(int *delta_w, int min, int max, int invert) +{ + int w = atomic_load(&mouse_w); + int real_w = invert ? -w : w; + + if (real_w > max) { + *delta_w = max; + real_w -= max; + } else if (real_w < min) { + *delta_w = min; + real_w += ABS(min); + } else { + *delta_w = real_w; + real_w = 0; + } + + atomic_store(&mouse_w, invert ? -real_w : real_w); +} + void mouse_set_buttons_ex(int b) { diff --git a/src/device/mouse_ps2.c b/src/device/mouse_ps2.c index 79d7afc96..0d34235fe 100644 --- a/src/device/mouse_ps2.c +++ b/src/device/mouse_ps2.c @@ -34,13 +34,15 @@ enum { MODE_ECHO }; -#define FLAG_EXPLORER 0x200 /* Has 5 buttons */ -#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */ -#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ -#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ -#define FLAG_SCALED 0x20 /* enable delta scaling */ -#define FLAG_ENABLED 0x10 /* dev is enabled for use */ -#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ +#define FLAG_HWHL 0x800 /* Report horizontal wheel movements. */ +#define FLAG_EXPLORER_HWHL 0x400 /* Has tilt-wheel/horizontal scroll wheel */ +#define FLAG_EXPLORER 0x200 /* Has 5 buttons */ +#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */ +#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ +#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ +#define FLAG_SCALED 0x20 /* enable delta scaling */ +#define FLAG_ENABLED 0x10 /* dev is enabled for use */ +#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ #define FIFO_SIZE 16 @@ -82,10 +84,16 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main) int overflow_y; int b = mouse_get_buttons_ex(); int delta_z; + int delta_w; mouse_subtract_coords(&delta_x, &delta_y, &overflow_x, &overflow_y, -256, 255, 1, 0); - mouse_subtract_z(&delta_z, -8, 7, 1); + + if (dev->flags & FLAG_5BTN) + mouse_subtract_z(&delta_z, -32, 31, 1); + else + mouse_subtract_z(&delta_z, -8, 7, 1); + mouse_subtract_w(&delta_w, -1, 1, 0); buff[0] |= (overflow_y << 7) | (overflow_x << 6) | ((delta_y & 0x0100) >> 3) | ((delta_x & 0x0100) >> 4) | @@ -97,10 +105,21 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main) kbc_at_dev_queue_add(dev, buff[1], main); kbc_at_dev_queue_add(dev, buff[2], main); if (dev->flags & FLAG_INTMODE) { - delta_z &= 0x0f; + delta_z &= (dev->flags & FLAG_HWHL) ? 0x3f : 0x0f; if (dev->flags & FLAG_5BTN) { - if (b & 8) + if ((dev->flags & FLAG_HWHL) && (delta_z || delta_w)) + { + if (delta_w) { + delta_z = delta_w; + delta_z &= 0x3f; + delta_z |= 0x40; + } else { + delta_z &= 0x3f; + delta_z |= 0x80; + } + } + else if (b & 8) delta_z |= 0x10; if (b & 16) delta_z |= 0x20; @@ -120,7 +139,7 @@ ps2_set_defaults(atkbc_dev_t *dev) dev->rate = 100; mouse_set_sample_rate(100.0); dev->resolution = 2; - dev->flags &= 0x188; + dev->flags &= 0x688; mouse_scan = 0; } @@ -298,6 +317,13 @@ ps2_write(void *priv) (last_data[2] == 0xf3) && (last_data[3] == 0xc8) && (last_data[4] == 0xf3) && (last_data[5] == 0x50)) dev->flags |= FLAG_5BTN; + + if ((dev->flags & FLAG_5BTN) && (dev->flags & FLAG_EXPLORER_HWHL) && + (last_data[0] == 0xf3) && (last_data[1] == 0xc8) && + (last_data[2] == 0xf3) && (last_data[3] == 0x50) && + (last_data[4] == 0xf3) && (last_data[5] == 0x28)) + dev->flags |= FLAG_HWHL; + } } @@ -336,6 +362,8 @@ mouse_ps2_init(const device_t *info) dev->flags |= FLAG_INTELLI; if (i > 4) dev->flags |= FLAG_EXPLORER; + if (i > 5) + dev->flags |= FLAG_EXPLORER_HWHL; mouse_ps2_log("%s: buttons=%d\n", dev->name, i); @@ -377,11 +405,12 @@ static const device_config_t ps2_config[] = { .file_filter = NULL, .spinner = { 0 }, .selection = { - { .description = "Two", .value = 2 }, - { .description = "Three", .value = 3 }, - { .description = "Wheel", .value = 4 }, - { .description = "Five + Wheel", .value = 5 }, - { .description = "" } + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "Wheel", .value = 4 }, + { .description = "Five + Wheel", .value = 5 }, + { .description = "Five + 2 Wheels", .value = 6 }, + { .description = "" } }, .bios = { { 0 } } }, diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index bbe78413b..333849846 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -100,6 +100,9 @@ extern void mouse_scale_axis(int axis, int val); extern void mouse_set_z(int z); extern void mouse_clear_z(void); extern void mouse_subtract_z(int *delta_z, int min, int max, int invert); +extern void mouse_set_w(int w); +extern void mouse_clear_w(void); +extern void mouse_subtract_w(int *delta_w, int min, int max, int invert); extern void mouse_set_buttons_ex(int b); extern int mouse_get_buttons_ex(void); extern void mouse_set_sample_rate(double new_rate); diff --git a/src/qt/macos_event_filter.mm b/src/qt/macos_event_filter.mm index ff4e7c4d2..45c8ecbe3 100644 --- a/src/qt/macos_event_filter.mm +++ b/src/qt/macos_event_filter.mm @@ -37,6 +37,7 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, return true; } if ([event type] == NSEventTypeScrollWheel) { + mouse_set_w(-[event deltaX]); mouse_set_z([event deltaY]); return true; } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 5dc61e03b..aed932e92 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -210,8 +210,10 @@ RendererStack::wheelEvent(QWheelEvent *event) #if !defined(Q_OS_WINDOWS) && !defined(__APPLE__) double numSteps = (double) event->angleDelta().y() / 120.0; + double numStepsW = (double) event->angleDelta().x() / 120.0; mouse_set_z((int) numSteps); + mouse_set_w((int) numStepsW); #endif event->accept(); } diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 8a2841f97..306da575f 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -330,6 +330,7 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) static int x, delta_x; static int y, delta_y; static int b, delta_z; + static int delta_w; b = mouse_get_buttons_ex(); @@ -367,6 +368,12 @@ WindowsRawInputFilter::mouse_handle(PRAWINPUT raw) } else delta_z = 0; + if (state.usButtonFlags & RI_MOUSE_HWHEEL) { + delta_w = (SHORT) state.usButtonData / 120; + mouse_set_w(delta_w); + } else + delta_w = 0; + if (state.usFlags & MOUSE_MOVE_ABSOLUTE) { /* absolute mouse, i.e. RDP or VNC * seems to work fine for RDP on Windows 10 From 46f7c7c46f14217f41572b5e77e9b8e328e8b922 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Mar 2025 06:20:22 +0100 Subject: [PATCH 067/158] MO and ZIP: Fix return length of READ 6/10/12 and actually save the image history into the configuration file. --- src/config.c | 26 ++++++++++++++++++++++++++ src/disk/mo.c | 1 + src/disk/zip.c | 6 ++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/config.c b/src/config.c index 3bb9fb59a..2e6a5460f 100644 --- a/src/config.c +++ b/src/config.c @@ -3011,6 +3011,19 @@ save_other_removable_devices(void) else ini_section_set_string(cat, temp, zip_drives[c].image_path); } + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "zip_%02i_image_history_%02i", c + 1, i + 1); + if ((zip_drives[c].image_history[i] == 0) || strlen(zip_drives[c].image_history[i]) == 0) + ini_section_delete_var(cat, temp); + else { + path_normalize(zip_drives[c].image_history[i]); + if (!strnicmp(zip_drives[c].image_history[i], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &zip_drives[c].image_history[i][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, zip_drives[c].image_history[i]); + } + } } for (c = 0; c < MO_NUM; c++) { @@ -3054,6 +3067,19 @@ save_other_removable_devices(void) else ini_section_set_string(cat, temp, mo_drives[c].image_path); } + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "mo_%02i_image_history_%02i", c + 1, i + 1); + if ((mo_drives[c].image_history[i] == 0) || strlen(mo_drives[c].image_history[i]) == 0) + ini_section_delete_var(cat, temp); + else { + path_normalize(mo_drives[c].image_history[i]); + if (!strnicmp(mo_drives[c].image_history[i], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &mo_drives[c].image_history[i][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, mo_drives[c].image_history[i]); + } + } } ini_delete_section_if_empty(config, cat); diff --git a/src/disk/mo.c b/src/disk/mo.c index e5cbd9140..d59343833 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1363,6 +1363,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_buf_alloc(dev, dev->packet_len); const int ret = mo_blocks(dev, &alloc_length, 0); + alloc_length = dev->requested_blocks * 512; if (ret > 0) { dev->requested_blocks = max_len; diff --git a/src/disk/zip.c b/src/disk/zip.c index ae3319b40..ed59154b0 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1386,10 +1386,8 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb) dev->packet_len = max_len * alloc_length; zip_buf_alloc(dev, dev->packet_len); - int ret = 0; - - if (dev->sector_len > 0) - ret = zip_blocks(dev, &alloc_length, 0); + const int ret = zip_blocks(dev, &alloc_length, 0); + alloc_length = dev->requested_blocks * 512; if (ret > 0) { dev->requested_blocks = max_len; From a886d8a9f0146907a2689795e2828023ab620300 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Mar 2025 06:20:55 +0100 Subject: [PATCH 068/158] Forgotten Cyrix-related fixes in mem.c. --- src/mem/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mem/mem.c b/src/mem/mem.c index d1c6de49d..d85b20581 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -2370,7 +2370,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size) for (i_c = i_s; i_c <= i_e; i_c += i_a) { for (c = (start + i_c); c < (end + i_c); c += MEM_GRANULARITY_SIZE) { /* CPU */ - n = !!in_smm; + n = (!!in_smm) || (is_cxsmm && (ccr1 & CCR1_SMAC)); wp = _mem_wp[c >> MEM_GRANULARITY_BITS]; if (map->exec && mem_mapping_access_allowed(map->flags, From f74db2660f2a7c2a7eeb1e08e1bf1284c38936b1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Mar 2025 06:25:49 +0100 Subject: [PATCH 069/158] Fix the exact same READ 10/12/16 bug in scsi_disk.c as well. --- src/scsi/scsi_disk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 878259094..a1afca2e2 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -1095,7 +1095,9 @@ scsi_disk_command(scsi_common_t *sc, const uint8_t *cdb) dev->drv->seek_pos = dev->sector_pos; dev->drv->seek_len = dev->sector_len; - ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); + ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); + alloc_length = dev->requested_blocks * 512; + if (ret > 0) { dev->requested_blocks = max_len; dev->packet_len = alloc_length; From 7575bdc562268f1660cd8bbc35e8aeae383cc167 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 20 Mar 2025 06:30:58 +0100 Subject: [PATCH 070/158] Fixed the MO part of the fix - do NOT hardcode to 512! --- src/disk/mo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index d59343833..c039695b5 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1363,7 +1363,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) mo_buf_alloc(dev, dev->packet_len); const int ret = mo_blocks(dev, &alloc_length, 0); - alloc_length = dev->requested_blocks * 512; + alloc_length = dev->requested_blocks * dev->drv->sector_size; if (ret > 0) { dev->requested_blocks = max_len; From a9c97abfb6ac90aff1c0d9ea7cf594a519ff374b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 20 Mar 2025 21:52:48 +0600 Subject: [PATCH 071/158] Pre-calculate `pow` table for FXTRACT instruction --- src/86box.c | 8 ++++++++ src/cpu/cpu.c | 3 +++ src/cpu/x87_ops.h | 2 ++ src/cpu/x87_ops_misc.h | 2 +- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index 5bf8177e8..310d0b5d3 100644 --- a/src/86box.c +++ b/src/86box.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifndef _WIN32 # include @@ -233,6 +234,8 @@ extern int CPUID; extern int output; int atfullspeed; +extern double exp_pow_table[0x800]; + char exe_path[2048]; /* path (dir) of executable */ char usr_path[1024]; /* path (dir) of user data */ char cfg_path[1024]; /* full path of config file */ @@ -1086,6 +1089,11 @@ pc_init_modules(void) machine_status_init(); + for (c = 0; c <= 0x7ff; c++) { + int64_t exp = c - 1023; /* 1023 = BIAS64 */ + exp_pow_table[c] = pow(2.0, (double) exp); + } + if (do_nothing) { do_nothing = 0; exit(-1); diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 41ca6932d..910d40765 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -287,6 +287,9 @@ uint8_t reg_30 = 0x00; uint8_t arr[24] = { 0 }; uint8_t rcr[8] = { 0 }; +/* Table for FXTRACT. */ +double exp_pow_table[0x800]; + static int cyrix_addr; static void cpu_write(uint16_t addr, uint8_t val, void *priv); diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 6a51a2c7f..0bd8209e1 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -36,6 +36,8 @@ extern void fpu_log(const char *fmt, ...); # endif #endif +extern double exp_pow_table[0x800]; + static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO }; #define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)] diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 4009eadd6..9a01f7496 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -46,7 +46,7 @@ opFXTRACT(UNUSED(uint32_t fetchdat)) test.eind.d = ST(0); exp80 = test.eind.ll & 0x7ff0000000000000LL; exp80final = (exp80 >> 52) - BIAS64; - mant = test.eind.d / (pow(2.0, (double) exp80final)); + mant = test.eind.d / exp_pow_table[exp80 >> 52]; ST(0) = (double) exp80final; FP_TAG_VALID; x87_push(mant); From 0ebadfb942a3233622a75e85ae3ea34e05053911 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Mar 2025 03:29:46 +0100 Subject: [PATCH 072/158] CD-ROM, ATAPI HDD, MO, and ZIP: correct bus speed arithmetic, makes especially MO and ZIP much faster. --- src/disk/mo.c | 37 +++++++++++++------------------------ src/disk/zip.c | 37 +++++++++++++------------------------ src/scsi/scsi_cdrom.c | 7 ++++--- src/scsi/scsi_disk.c | 7 ++++++- 4 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/disk/mo.c b/src/disk/mo.c index c039695b5..f1cd3b983 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -486,19 +486,16 @@ mo_bus_speed(mo_t *dev) { double ret = -1.0; - if (dev && dev->drv && (dev->drv->bus_type == MO_BUS_SCSI)) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return 0.0; - } else { - if (dev && dev->drv) - ret = ide_atapi_get_period(dev->drv->ide_channel); - if (ret == -1.0) { - if (dev) - dev->callback = -1.0; - return 0.0; - } else - return ret * 1000000.0; + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + ret = 0.0; } + + return ret; } static void @@ -509,18 +506,10 @@ mo_command_common(mo_t *dev) dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) dev->callback = 0.0; - else { - double bytes_per_second; - - if (dev->drv->bus_type == MO_BUS_SCSI) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return; - } else - bytes_per_second = mo_bus_speed(dev); - - const double period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); - } + else if (dev->drv->bus_type == MO_BUS_SCSI) + dev->callback = -1.0; /* Speed depends on SCSI controller */ + else + dev->callback = mo_bus_speed(dev) * (double) (dev->packet_len); mo_set_callback(dev); } diff --git a/src/disk/zip.c b/src/disk/zip.c index ed59154b0..eecafb802 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -567,19 +567,16 @@ zip_bus_speed(zip_t *dev) { double ret = -1.0; - if (dev && dev->drv && (dev->drv->bus_type == ZIP_BUS_SCSI)) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return 0.0; - } else { - if (dev && dev->drv) - ret = ide_atapi_get_period(dev->drv->ide_channel); - if (ret == -1.0) { - if (dev) - dev->callback = -1.0; - return 0.0; - } else - return ret * 1000000.0; + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + ret = 0.0; } + + return ret; } static void @@ -590,18 +587,10 @@ zip_command_common(zip_t *dev) dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) dev->callback = 0.0; - else { - double bytes_per_second; - - if (dev->drv->bus_type == ZIP_BUS_SCSI) { - dev->callback = -1.0; /* Speed depends on SCSI controller */ - return; - } else - bytes_per_second = zip_bus_speed(dev); - - double period = 1000000.0 / bytes_per_second; - dev->callback = period * (double) (dev->packet_len); - } + else if (dev->drv->bus_type == ZIP_BUS_SCSI) + dev->callback = -1.0; /* Speed depends on SCSI controller */ + else + dev->callback = zip_bus_speed(dev) * (double) (dev->packet_len); zip_set_callback(dev); } diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index b35662eeb..9ae65be74 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -656,7 +656,7 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) dev->callback = -1.0; return 0.0; } else - return ret * 1000000.0; + return 1000000.0 / ret; } } @@ -1069,8 +1069,9 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, const int msf, const int type, const int dev->block_len = temp_len; if ((dev->drv->bus_type != CDROM_BUS_SCSI) && - (scsi_cdrom_current_mode(dev) != 2)) + (scsi_cdrom_current_mode(dev) != 2)) { num = (dev->packet_len / dev->block_len); + } } dev->sector_pos++; @@ -1126,7 +1127,7 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev) } if (ret) { - if (!dev->sector_len) { + if (dev->sector_len == 0) { scsi_cdrom_command_complete(dev); return -1; } diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index a1afca2e2..8528db1fb 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -400,7 +400,8 @@ scsi_disk_bus_speed(scsi_disk_t *dev) dev->callback = -1.0; return 0.0; } else - return ret * 1000000.0; + /* We get bytes per µs, so divide 1000000.0 by it. */ + return 1000000.0 / ret; } } @@ -484,6 +485,10 @@ scsi_disk_command_common(scsi_disk_t *dev) break; } + /* + For ATAPI, this will be 1000000.0 / µs_per_byte, and this will + convert it back to µs_per_byte. + */ period = 1000000.0 / bytes_per_second; scsi_disk_log(dev->log, "Byte transfer period: %" PRIu64 " us\n", (uint64_t) period); From 63f106a0fd888d994dfae60244e36ae718a01551 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 00:49:20 +0100 Subject: [PATCH 073/158] Added plat_break() for raising breakpoints and warning() and log_warning() to raise visible non-fatal warnings to the user. --- src/86box.c | 69 +++++++++++++++++++++++++++++++++++++++ src/include/86box/86box.h | 7 ++-- src/include/86box/log.h | 1 + src/include/86box/plat.h | 1 + src/qt/qt_platform.cpp | 10 ++++++ src/utils/log.c | 25 ++++++++++++++ 6 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/86box.c b/src/86box.c index 310d0b5d3..dbf58a70e 100644 --- a/src/86box.c +++ b/src/86box.c @@ -440,6 +440,75 @@ fatal_ex(const char *fmt, va_list ap) fflush(stdlog); } +/* Log a warning error, and display a UI message without exiting. */ +void +warning(const char *fmt, ...) +{ + char temp[1024]; + va_list ap; + char *sp; + + va_start(ap, fmt); + + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } + + vsprintf(temp, fmt, ap); + fprintf(stdlog, "%s", temp); + fflush(stdlog); + va_end(ap); + + /* Make sure the message does not have a trailing newline. */ + if ((sp = strchr(temp, '\n')) != NULL) + *sp = '\0'; + + do_pause(2); + + ui_msgbox(MBX_ERROR | MBX_ANSI, temp); + + fflush(stdlog); + + do_pause(0); +} + +void +warning_ex(const char *fmt, va_list ap) +{ + char temp[1024]; + char *sp; + + if (stdlog == NULL) { + if (log_path[0] != '\0') { + stdlog = plat_fopen(log_path, "w"); + if (stdlog == NULL) + stdlog = stdout; + } else + stdlog = stdout; + } + + vsprintf(temp, fmt, ap); + fprintf(stdlog, "%s", temp); + fflush(stdlog); + + /* Make sure the message does not have a trailing newline. */ + if ((sp = strchr(temp, '\n')) != NULL) + *sp = '\0'; + + do_pause(2); + + ui_msgbox(MBX_ERROR | MBX_ANSI, temp); + + fflush(stdlog); + + do_pause(0); +} + #ifdef ENABLE_PC_LOG int pc_do_log = ENABLE_PC_LOG; diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 40e1f7927..174685c34 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -194,15 +194,12 @@ extern __thread int is_cpu_thread; /* Is this the CPU thread? */ #ifdef HAVE_STDARG_H extern void pclog_ex(const char *fmt, va_list ap); extern void fatal_ex(const char *fmt, va_list ap); +extern void warning_ex(const char *fmt, va_list ap); #endif extern void pclog_toggle_suppr(void); -#ifdef _MSC_VER -extern void pclog(const char *fmt, ...); -extern void fatal(const char *fmt, ...); -#else extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -#endif +extern void warning(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); extern void set_screen_size(int x, int y); extern void set_screen_size_monitor(int x, int y, int monitor_index); extern void reset_screen_size(void); diff --git a/src/include/86box/log.h b/src/include/86box/log.h index a37bdec4f..e247ef9c5 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -36,6 +36,7 @@ extern void log_out(void *priv, const char *fmt, va_list); extern void log_out_cyclic(void* priv, const char *fmt, va_list); #endif /*RELEASE_BUILD*/ extern void log_fatal(void *priv, const char *fmt, ...); +extern void log_warning(void *priv, const char *fmt, ...); extern void *log_open(const char *dev_name); extern void *log_open_cyclic(const char *dev_name); extern void log_close(void *priv); diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 81874685e..7ed6e80d4 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -164,6 +164,7 @@ extern uint32_t plat_language_code(char *langcode); extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len); extern void plat_get_cpu_string(char *outbuf, uint8_t len); extern void plat_set_thread_name(void *thread, const char *name); +extern void plat_break(void); /* Resource management. */ extern wchar_t *plat_get_string(int id); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index ebd6dc30c..1364750b1 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -842,3 +842,13 @@ plat_set_thread_name(void *thread, const char *name) # endif #endif } + +void +plat_break(void) +{ +#ifdef Q_OS_WINDOWS + DebugBreak(); +#else + raise(SIGTRAP); +#endif +} diff --git a/src/utils/log.c b/src/utils/log.c index c8dddf62e..257029b51 100644 --- a/src/utils/log.c +++ b/src/utils/log.c @@ -294,6 +294,31 @@ log_fatal(void *priv, const char *fmt, ...) exit(-1); } +void +log_warning(void *priv, const char *fmt, ...) +{ + log_t *log = (log_t *) priv; + char temp[1024]; + char fmt2[1024]; + va_list ap; + + if (log == NULL) + return; + + if (log->cyclic_buff != NULL) { + for (int i = 0; i < LOG_SIZE_BUFFER_CYCLIC_LINES; i++) + if (log->cyclic_buff[i] != NULL) + free(log->cyclic_buff[i]); + free(log->cyclic_buff); + } + + va_start(ap, fmt); + log_copy(log, fmt2, fmt, 1024); + vsprintf(temp, fmt2, ap); + warning_ex(fmt2, ap); + va_end(ap); +} + static void * log_open_common(const char *dev_name, const int cyclic) { From 81141c574ceb25b20faf221ba0877d2becb24530 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 02:14:31 +0100 Subject: [PATCH 074/158] #include on non-Windows platforms. --- src/qt/qt_platform.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 1364750b1..0df64c4dc 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -54,6 +54,10 @@ #include "qt_progsettings.hpp" #include "qt_util.hpp" +#ifndef Q_OS_WINDOWS +# include +#endif + #ifdef Q_OS_UNIX # include # include From 50e77917d5309ea69a606a3c8af03be15a9447c8 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 23 Mar 2025 00:42:51 +0900 Subject: [PATCH 075/158] Fix for NetBSD --- src/CMakeLists.txt | 4 ++++ src/include/86box/86box.h | 5 +++++ src/include/86box/bswap.h | 6 ++---- src/include/86box/log.h | 5 +++++ src/qt/qt_platform.cpp | 2 +- src/unix/unix_serial_passthrough.c | 4 ++++ 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aac413aae..8cf67043f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -263,3 +263,7 @@ else() add_compile_definitions(USE_SDL_UI) add_subdirectory(unix) endif() + +if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + add_custom_command(TARGET 86Box POST_BUILD COMMAND paxctl ARGS +m $ COMMENT "Disable PaX MPROTECT") +endif() diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 174685c34..e8c5fbac9 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -20,6 +20,11 @@ #ifndef EMU_86BOX_H #define EMU_86BOX_H +#ifdef __NetBSD__ +/* Doesn't compile on NetBSD without this include */ +#include +#endif + /* Configuration values. */ #define GFXCARD_MAX 2 #define SERIAL_MAX 7 diff --git a/src/include/86box/bswap.h b/src/include/86box/bswap.h index 37c846d59..61a6a46a2 100644 --- a/src/include/86box/bswap.h +++ b/src/include/86box/bswap.h @@ -35,13 +35,12 @@ * USA. */ -#ifndef __NetBSD__ - #ifndef BSWAP_H #define BSWAP_H #include +#ifndef __NetBSD__ #define bswap_16(x) \ ((uint16_t)((((x) & 0x00ffu) << 8) | \ (((x) & 0xff00u) >> 8))) @@ -91,6 +90,7 @@ bswap64(uint64_t x) return bswap_16(x); #endif } +#endif static __inline void bswap16s(uint16_t *s) @@ -241,5 +241,3 @@ cpu_to_be32wu(uint32_t *p, uint32_t v) #undef be_bswaps #endif /*BSWAP_H*/ - -#endif diff --git a/src/include/86box/log.h b/src/include/86box/log.h index e247ef9c5..80ed6d108 100644 --- a/src/include/86box/log.h +++ b/src/include/86box/log.h @@ -24,6 +24,11 @@ extern "C" { # endif +#ifdef __NetBSD__ +/* Doesn't compile on NetBSD without this include */ +#include +#endif + #define LOG_SIZE_BUFFER 1024 /* Log size buffer */ #define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */ #define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */ diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 0df64c4dc..e8a02fc3b 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -836,7 +836,7 @@ plat_set_thread_name(void *thread, const char *name) # if defined(Q_OS_DARWIN) pthread_setname_np(truncated); # elif defined(Q_OS_NETBSD) - pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated, "%s"); + pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated, (void*)"%s"); # elif defined(__HAIKU__) rename_thread(find_thread(NULL), truncated); # elif defined(Q_OS_OPENBSD) diff --git a/src/unix/unix_serial_passthrough.c b/src/unix/unix_serial_passthrough.c index a12346013..9929f3298 100644 --- a/src/unix/unix_serial_passthrough.c +++ b/src/unix/unix_serial_passthrough.c @@ -26,6 +26,7 @@ #endif #ifdef __NetBSD__ # define _NETBSD_VISIBLE 1 +# define _NETBSD_SOURCE 1 #endif #include #include @@ -149,8 +150,11 @@ plat_serpt_set_params(void *priv) BAUDRATE_RANGE(dev->baudrate, 9600, 19200, B9600); BAUDRATE_RANGE(dev->baudrate, 19200, 38400, B19200); BAUDRATE_RANGE(dev->baudrate, 38400, 57600, B38400); +#ifndef __NetBSD__ + /* nonexistent on NetBSD */ BAUDRATE_RANGE(dev->baudrate, 57600, 115200, B57600); BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF, B115200); +#endif term_attr.c_cflag &= ~CSIZE; switch (dev->data_bits) { From a19c99eb64c85a455ad81a693fc46e5919ff5db8 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 23 Mar 2025 01:19:57 +0900 Subject: [PATCH 076/158] Fix JP translation --- src/qt/languages/ja-JP.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 9c6fa66e7..6132a8db1 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -868,7 +868,7 @@ msgid "Hardware not available" msgstr "ハードウェアが利用できません" msgid "Make sure %1 is installed and that you are on a %1-compatible network connection." -msgstr "がインストールされてるか、%1に対応したネットワークに接続されてるか確認してください。" +msgstr "%1がインストールされていてかつ、%1に対応したネットワークに接続されてるか確認してください。" msgid "Invalid configuration" msgstr "不正な設定です" @@ -910,10 +910,10 @@ msgid "OpenGL options" msgstr "OpenGL設定" msgid "You are loading an unsupported configuration" -msgstr "読み込んでいる設定がサポートされません" +msgstr "サポートされていないコンフィグを読み込んでいます" msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid." -msgstr "選択したマシンに基づくCPUタイプのフィルター機能は、使用中のマシンでは無効になっています。\n\nこれにより、選択したマシンと互換性のないCPUが選択できます。しかし、マシンのBIOSや他のソフトウェアと互換性がない場合があります。\n\nこの設定を有効にすることは公式にはサポートされておらず、バグレポートは無効として中止される可能性があります。" +msgstr "選択したマシンに基づくCPUタイプのフィルター機能は、使用中のマシンでは無効になっています。\n\nこれにより、選択したマシンと互換性のないCPUが選択できます。しかし、マシンのBIOSや他のソフトウェアと互換性がない場合があります。\n\nこの設定を有効にすることは公式にはサポートされておらず、バグレポートは無効としてクローズされる可能性があります。" msgid "Continue" msgstr "続行" @@ -1015,7 +1015,7 @@ msgid "The selected file will be overwritten. Are you sure you want to use it?" msgstr "選択したファイルは上書きされます。よろしいですか?" msgid "Unsupported disk image" -msgstr "非対応のディスクイメージジ" +msgstr "非対応のディスクイメージ" msgid "Overwrite" msgstr "上書き" @@ -1285,7 +1285,7 @@ msgid "Host CD/DVD Drive (%1)" msgstr "ホスト CD/DVD ドライブ (%1)" msgid "Unknown Bus" -msgstr "不明バス" +msgstr "不明なバス" msgid "Null Driver" msgstr "ヌル・ドライバー" @@ -1294,7 +1294,7 @@ msgid "NIC %02i (%ls) %ls" msgstr "NIC %02i (%ls) %ls" msgid "Error opening \"%1\": %2" -msgstr "エラー・オープニング\"%1\": %2" +msgstr "\"%1\"を開く際にエラーが発生しました: %2" msgid "Error compiling vertex shader in file \"%1\"" msgstr "ファイル\"%1\"の頂点シェーダのコンパイルエラー。" From c3d15ef36d183cb54df75466de5bb26fd38ce8d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 19:45:32 +0100 Subject: [PATCH 077/158] EGA and JEGA: Implement some missing SuperEGA stuff and make the JEGA properly set the EGA type to SuperEGA, fixes #5370. --- src/include/86box/vid_ega.h | 1 + src/video/vid_ega.c | 69 +++++++++++++++++++++++++++++++++---- src/video/vid_jega.c | 2 +- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 082cb120a..5ff7d3871 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -178,6 +178,7 @@ extern uint8_t ega_in(uint16_t addr, void *priv); extern void ega_poll(void *priv); extern void ega_write(uint32_t addr, uint8_t val, void *priv); extern uint8_t ega_read(uint32_t addr, void *priv); +extern void ega_set_type(void *priv, uint32_t local); extern int firstline_draw; extern int lastline_draw; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 781e9a9dd..18a53a127 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -67,6 +67,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega_t *ega = (ega_t *) priv; uint8_t o; uint8_t old; + uint8_t gdcmask = (ega->actual_type == EGA_SUPEREGA) ? 0xff : 0x0f; + uint8_t crtcmask = (ega->actual_type == EGA_SUPEREGA) ? 0xff : 0x1f; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -200,8 +202,8 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->gdcaddr = val; break; case 0x3cf: - ega->gdcreg[ega->gdcaddr & 15] = val; - switch (ega->gdcaddr & 15) { + ega->gdcreg[ega->gdcaddr & gdcmask] = val; + switch (ega->gdcaddr & gdcmask) { case 2: ega->colourcompare = val; break; @@ -238,6 +240,19 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->colournocare = val; break; + case 0xf8: + ega->la = val; + break; + case 0xf9: + ega->lb = val; + break; + case 0xfa: + ega->lc = val; + break; + case 0xfb: + ega->ld = val; + break; + default: break; } @@ -247,7 +262,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if (ega->chipset) ega->crtcreg = val & 0x3f; else - ega->crtcreg = val & 0x1f; + ega->crtcreg = val & crtcmask; return; case 0x3d1: case 0x3d5: @@ -286,7 +301,8 @@ uint8_t ega_in(uint16_t addr, void *priv) { ega_t *ega = (ega_t *) priv; - uint8_t ret = 0xff; + uint8_t gdcmask = (ega->actual_type == EGA_SUPEREGA) ? 0xff : 0x0f; + uint8_t ret = 0xff; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) addr ^= 0x60; @@ -347,8 +363,25 @@ ega_in(uint16_t addr, void *priv) ret = ega->gdcaddr; break; case 0x3cf: - if (ega_type == EGA_TYPE_OTHER) - ret = ega->gdcreg[ega->gdcaddr & 0xf]; + if (ega_type == EGA_TYPE_OTHER) { + switch (ega->gdcaddr & gdcmask) { + default: + ret = ega->gdcreg[ega->gdcaddr & gdcmask]; + break; + case 0xf8: + ret = ega->la; + break; + case 0xf9: + ret = ega->lb; + break; + case 0xfa: + ret = ega->lc; + break; + case 0xfb: + ret = ega->ld; + break; + } + } break; case 0x3d0: case 0x3d4: @@ -1428,6 +1461,30 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) timer_add(&ega->dot_timer, ega_dot_poll, ega, 1); } +void +ega_set_type(void *priv, uint32_t local) +{ + ega_t *ega = (ega_t *) priv; + + if ((local == EGA_IBM) || (local == EGA_ISKRA) || (local == EGA_TSENG)) + ega_type = EGA_TYPE_IBM; + else if (local == EGA_COMPAQ) + ega_type = EGA_TYPE_COMPAQ; + else + ega_type = EGA_TYPE_OTHER; + + ega->actual_type = local; + ega->chipset = 0; + + switch (local) { + default: + break; + case EGA_ATI800P: + ega->chipset = 1; + break; + } +} + static void * ega_standalone_init(const device_t *info) { diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index c410a15da..145579cf5 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -632,7 +632,7 @@ jega_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); jega->pallook = pallook64; ega_init(&jega->ega, 9, 0); - jega->ega.actual_type = EGA_SUPEREGA; + ega_set_type(&jega->ega, EGA_SUPEREGA); jega->ega.priv_parent = jega; mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); From 5fe9cc76da31fdef1bf598967d7db565ed12d480 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 20:44:56 +0100 Subject: [PATCH 078/158] SuperEGA: Increase the GDC and CRTC register arrays to 256 elements to prevent overflows and correctly ignore the upper 3 bits of CRTC register 07h in ega_recalctimings(), fixes #4905. --- src/video/vid_ega.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 18a53a127..17fea7b81 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -486,19 +486,19 @@ ega_recalctimings(ega_t *ega) if (ega->crtc[7] & 1) ega->vtotal |= 0x100; - if (ega->crtc[7] & 32) + if ((ega->actual_type != EGA_SUPEREGA) && (ega->crtc[7] & 32)) ega->vtotal |= 0x200; ega->vtotal += 2; if (ega->crtc[7] & 2) ega->dispend |= 0x100; - if (ega->crtc[7] & 64) + if ((ega->actual_type != EGA_SUPEREGA) && (ega->crtc[7] & 64)) ega->dispend |= 0x200; ega->dispend++; if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100; - if (ega->crtc[7] & 128) + if ((ega->actual_type != EGA_SUPEREGA) && (ega->crtc[7] & 128)) ega->vsyncstart |= 0x200; ega->vsyncstart++; From fb0704de993e36efce50ec731df13386a696c4d6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 21:23:07 +0100 Subject: [PATCH 079/158] Forgot vid_ega.h. --- src/include/86box/vid_ega.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 5ff7d3871..79375a2ae 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -47,8 +47,8 @@ typedef struct ega_t { uint8_t ctl_mode; uint8_t color_mux; uint8_t dot; - uint8_t crtc[32]; - uint8_t gdcreg[16]; + uint8_t crtc[256]; + uint8_t gdcreg[256]; uint8_t attrregs[32]; uint8_t seqregs[64]; uint8_t egapal[16]; From 2151a6064feaa9293889a5c014534ff1925b9e58 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 22 Mar 2025 23:57:05 +0100 Subject: [PATCH 080/158] SuperEGA: Implement row and vertical divide modes. --- src/include/86box/vid_ega.h | 1 + src/video/vid_ega.c | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 79375a2ae..4b7d32ea0 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -73,6 +73,7 @@ typedef struct ega_t { int oddeven_page; int oddeven_chain; int vc; + int real_vc; int sc; int dispon; int hdisp_on; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 17fea7b81..c7345cd00 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -620,11 +620,15 @@ ega_recalctimings(ega_t *ega) ega->y_add >>= 1; if (ega->seqregs[1] & 8) { - disptime = (double) ((ega->crtc[0] + 2) << 1); - _dispontime = (double) ((ega->crtc[1] + 1) << 1); + disptime = (double) ((ega->crtc[0] + 2) << 1); + _dispontime = (double) ((ega->crtc[1] + 1) << 1); } else { - disptime = (double) (ega->crtc[0] + 2); - _dispontime = (double) (ega->crtc[1] + 1); + disptime = (double) (ega->crtc[0] + 2); + _dispontime = (double) (ega->crtc[1] + 1); + } + if ((ega->actual_type == EGA_SUPEREGA) && (ega->crtc[0xf9] & 0x01)) { + disptime *= 2.0; + _dispontime *= 2.0; } _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; @@ -852,7 +856,10 @@ ega_poll(void *priv) ega->cca = ega->maback; } } - ega->vc++; + ega->real_vc++; + if ((ega->actual_type != EGA_SUPEREGA) || !(ega->crtc[0xf9] & 0x02) || + !(ega->real_vc & 1)) + ega->vc++; if (ega->chipset) { if (ega->hdisp > 640) ega->vc &= 1023; @@ -905,9 +912,13 @@ ega_poll(void *priv) if (ega->vres) { wy = (ega->lastline - ega->firstline) << 1; + if ((ega->actual_type == EGA_SUPEREGA) && (ega->crtc[0xf9] & 0x02)) + wy >>= 1; ega_doblit(wx, wy, ega); } else { wy = ega->lastline - ega->firstline; + if ((ega->actual_type == EGA_SUPEREGA) && (ega->crtc[0xf9] & 0x02)) + wy >>= 1; ega_doblit(wx, wy, ega); } From 646e25f1bc524f21fc6a74045986142652c1cb21 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 02:22:10 +0100 Subject: [PATCH 081/158] EGA: Implement monochrome attributes for text mode. --- src/video/vid_ega.c | 20 ++++++++++++++++++++ src/video/vid_ega_render.c | 12 ++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index c7345cd00..438d5c98d 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -1447,6 +1447,26 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) ega->pallook = pallook16; + for (uint16_t c = 0; c < 256; c++) { + ega->mdacols[c][0][0] = ega->mdacols[c][1][0] = ega->mdacols[c][1][1] = 16; + if (c & 8) + ega->mdacols[c][0][1] = 15 + 16; + else + ega->mdacols[c][0][1] = 7 + 16; + } + ega->mdacols[0x70][0][1] = 16; + ega->mdacols[0x70][0][0] = ega->mdacols[0x70][1][0] = ega->mdacols[0x70][1][1] = 16 + 15; + ega->mdacols[0xF0][0][1] = 16; + ega->mdacols[0xF0][0][0] = ega->mdacols[0xF0][1][0] = ega->mdacols[0xF0][1][1] = 16 + 15; + ega->mdacols[0x78][0][1] = 16 + 7; + ega->mdacols[0x78][0][0] = ega->mdacols[0x78][1][0] = ega->mdacols[0x78][1][1] = 16 + 15; + ega->mdacols[0xF8][0][1] = 16 + 7; + ega->mdacols[0xF8][0][0] = ega->mdacols[0xF8][1][0] = ega->mdacols[0xF8][1][1] = 16 + 15; + ega->mdacols[0x00][0][1] = ega->mdacols[0x00][1][1] = 16; + ega->mdacols[0x08][0][1] = ega->mdacols[0x08][1][1] = 16; + ega->mdacols[0x80][0][1] = ega->mdacols[0x80][1][1] = 16; + ega->mdacols[0x88][0][1] = ega->mdacols[0x88][1][1] = 16; + egaswitches = monitor_type & 0xf; ega->vram_limit = 256 * 1024; diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index fe2632574..d499154e6 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -118,6 +118,7 @@ ega_render_text(ega_t *ega) const bool doublewidth = ((ega->seqregs[1] & 8) != 0); const bool attrblink = ((ega->attrregs[0x10] & 8) != 0); const bool attrlinechars = (ega->attrregs[0x10] & 4); + const bool monoattrs = (ega->attrregs[0x10] & 2); const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); const bool seq9dot = ((ega->seqregs[1] & 1) == 0); const int dwshift = doublewidth ? 1 : 0; @@ -174,8 +175,15 @@ ega_render_text(ega_t *ega) if ((chr & ~0x1F) == 0xC0 && attrlinechars) dat |= (dat >> 1) & 1; - for (int xx = 0; xx < charwidth; xx++) - p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; + for (int xx = 0; xx < charwidth; xx++) { + if (monoattrs) { + if ((ega->sc == (ega->crtc[0x14] + 1)) && ((attr & 7) == 1)) + p[xx] = ega->mdacols[attr][attrblink][1]; + else + p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; + } else + p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; + } ega->ma += 4; p += charwidth; From ae60590133a28a873ef5d974ff6d52db34bdf0ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 02:26:03 +0100 Subject: [PATCH 082/158] EGA: Fix underline position. --- src/video/vid_ega_render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index d499154e6..af2402414 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -177,7 +177,7 @@ ega_render_text(ega_t *ega) for (int xx = 0; xx < charwidth; xx++) { if (monoattrs) { - if ((ega->sc == (ega->crtc[0x14] + 1)) && ((attr & 7) == 1)) + if ((ega->sc == ega->crtc[0x14]) && ((attr & 7) == 1)) p[xx] = ega->mdacols[attr][attrblink][1]; else p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; From 47aa4a1e1881bbe669f477399f3f2bc6d9d83c3b Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 02:29:41 +0100 Subject: [PATCH 083/158] EGA: Process the results of the monochrome attributes into 32-bit RGB values. --- src/video/vid_ega_render.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index af2402414..dd393e4b6 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -189,6 +189,9 @@ ega_render_text(ega_t *ega) p += charwidth; } ega->ma &= 0x3ffff; + + if (monoattrs) + video_process_8(ega->hdisp + ega->scrollcache, ega->displine); } } From 2ff31188c2ae62475e5c04f1886c7b9c131ec5ab Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 06:57:40 +0100 Subject: [PATCH 084/158] CGA: Fix rounding in the interpolation calculation. --- src/video/vid_cga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index f439cb1d8..a24162019 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -442,7 +442,7 @@ cga_interpolate_linear(uint8_t co1, uint8_t co2, double fraction) r2 = pow((r1 >= 0.0) ? r1 : -r1, 1.0 / 2.19921875); if (r1 <= 0.0) r2 = -r2; - ret = (uint8_t) (r2 * 255.0); + ret = (uint8_t) round(r2 * 255.0); return ret; } From c5efce619f49b58a67ed45123c970bb43d4dd275 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 07:14:52 +0100 Subject: [PATCH 085/158] And the forgotten vid_ega.h. --- src/include/86box/vid_ega.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 4b7d32ea0..5ac5c24e3 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -53,7 +53,6 @@ typedef struct ega_t { uint8_t seqregs[64]; uint8_t egapal[16]; uint8_t regs[256]; - uint8_t *vram; uint16_t light_pen; @@ -114,6 +113,9 @@ typedef struct ega_t { int remap_required; int actual_type; int chipset; + int mono_display; + + int mdacols[256][2][2]; uint32_t charseta; uint32_t charsetb; From c65b7bda6621b4ba98cbf4bc24f3d4d477dcb3de Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sun, 23 Mar 2025 14:26:07 +0100 Subject: [PATCH 086/158] IBM PS/2 Model 30-286 fixes the real machine supports 512 KB RAM configurations and ISA video cards --- src/machine/machine_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bae9de29f..c253bc029 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2756,11 +2756,11 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, + .flags = MACHINE_XTA | MACHINE_VIDEO, .ram = { - .min = 1024, + .min = 512, .max = 16384, - .step = 1024 + .step = 512 }, .nvrmask = 127, .kbc_device = NULL, From 609f34cc492ad670bcba59f11c3092a156b3d628 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 23 Mar 2025 15:36:05 +0100 Subject: [PATCH 087/158] Only flush write MMU cache on WP flag toggle as read and execute MMU cache is not affected by the flag. --- src/cpu/x86_ops_mov_ctrl.h | 10 ++++++---- src/cpu/x86_ops_mov_ctrl_2386.h | 10 ++++++---- src/include/86box/mem.h | 1 + src/mem/mem.c | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index b4f0c498a..253dc059e 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -184,7 +184,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { if (is_p6 || cpu_use_dynarec) @@ -193,7 +193,8 @@ opMOV_CRx_r_a16(uint32_t fetchdat) flushmmucache_nopc(); cpu_flush_pending = 1; } - } + } else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG) + flushmmucache_write(); /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -249,7 +250,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { if (is_p6 || cpu_use_dynarec) @@ -258,7 +259,8 @@ opMOV_CRx_r_a32(uint32_t fetchdat) flushmmucache_nopc(); cpu_flush_pending = 1; } - } + } else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG) + flushmmucache_write(); /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h index 13e08a145..8827d29b2 100644 --- a/src/cpu/x86_ops_mov_ctrl_2386.h +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -180,12 +180,13 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { flushmmucache_nopc(); cpu_flush_pending = 1; - } + } else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG) + flushmmucache_write(); /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -241,12 +242,13 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001) flushmmucache(); else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { flushmmucache_nopc(); cpu_flush_pending = 1; - } + } else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG) + flushmmucache_write(); /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 19a331925..81b46b2fa 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -448,6 +448,7 @@ extern void mem_flush_write_page(uint32_t addr, uint32_t virt); extern void mem_reset_page_blocks(void); extern void flushmmucache(void); +extern void flushmmucache_write(void); extern void flushmmucache_pc(void); extern void flushmmucache_nopc(void); diff --git a/src/mem/mem.c b/src/mem/mem.c index d85b20581..94c4ab788 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -225,6 +225,21 @@ flushmmucache(void) #endif } +void +flushmmucache_write(void) +{ + for (uint16_t c = 0; c < 256; c++) { + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + page_lookupp[writelookup[c]] = 4; + writelookup2[writelookup[c]] = LOOKUP_INV; + writelookupp[writelookup[c]] = 4; + writelookup[c] = 0xffffffff; + } + } + mmuflush++; +} + void flushmmucache_pc(void) { From 8cc81683f7da568a4d7bad14889eb0370d887797 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Sun, 23 Mar 2025 15:48:47 +0100 Subject: [PATCH 088/158] Change back to fixed video, apparently 86Box had it set to fixed due to bugs in 86Box itself --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c253bc029..b38e42310 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2756,7 +2756,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PS2, - .flags = MACHINE_XTA | MACHINE_VIDEO, + .flags = MACHINE_XTA | MACHINE_VIDEO_FIXED, .ram = { .min = 512, .max = 16384, From 97707a9831d1b435b32d36a6cd24251dfefb4c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:18:48 +0100 Subject: [PATCH 089/158] net_modem: fix response to unrecognized will/wont telnet commands --- src/network/net_modem.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/network/net_modem.c b/src/network/net_modem.c index a8eab4290..af97a16db 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -1177,9 +1177,15 @@ modem_process_telnet(modem_t *modem, uint8_t *data, uint32_t size) uint8_t c = data[i]; if (modem->telClient.inIAC) { if (modem->telClient.recCommand) { + modem_log("modem_process_telnet: received command %i, option %i\n", modem->telClient.command, c); + if ((c != 0) && (c != 1) && (c != 3)) { - if (modem->telClient.command > 250) { - /* Reject anything we don't recognize */ + /* Reject anything we don't recognize */ + if (modem->telClient.command == 251 || modem->telClient.command == 252) { + modem_data_mode_process_byte(modem, 0xff); + modem_data_mode_process_byte(modem, 254); + modem_data_mode_process_byte(modem, c); /* Don't do crap! */ + } else if (modem->telClient.command == 253 || modem->telClient.command == 254) { modem_data_mode_process_byte(modem, 0xff); modem_data_mode_process_byte(modem, 252); modem_data_mode_process_byte(modem, c); /* We won't do crap! */ From 512c04c9f4443f7a1c3b7147d13acb18819de04f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 00:56:34 +0900 Subject: [PATCH 090/158] Add OKI if386AX emulation (#7) * add a machine oki if386ax * if386AX: still in debug * Revert "if386AX: still in debug" This reverts commit ade401beb0c72cee6fd1ec4728097a87e75bc09b. * if386ax: added I/O 6xh * if386ax: remove comment * formatting, sorting, change filename * change mono color palette --- src/include/86box/machine.h | 1 + src/include/86box/video.h | 3 + src/machine/m_at_286_386sx.c | 25 +++++ src/machine/machine_table.c | 38 ++++++++ src/video/vid_ega.c | 6 +- src/video/vid_jega.c | 171 ++++++++++++++++++++++++++++++----- 6 files changed, 216 insertions(+), 28 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d1257d94c..21e4a89e2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -483,6 +483,7 @@ extern int machine_at_adi386sx_init(const machine_t *); extern int machine_at_cmdsl386sx16_init(const machine_t *); extern int machine_at_cmdsl386sx25_init(const machine_t *); extern int machine_at_dataexpert386sx_init(const machine_t *); +extern int machine_at_if386sx_init(const machine_t *); extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_arb1374_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 2985559e1..6cf9c8d59 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -456,6 +456,9 @@ extern const device_t millennium_ii_device; extern const device_t productiva_g100_device; #endif /* USE_G100 */ +/* JEGA */ +extern const device_t if386jega_device; + /* Oak OTI-0x7 */ extern const device_t oti037c_device; extern const device_t oti067_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index fd9cc3bcd..2f35427be 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -641,6 +641,31 @@ machine_at_cmdsl386sx16_init(const machine_t *model) return ret; } +int +machine_at_if386sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/if386sx/OKI_IF386SX_odd.bin", + "roms/machines/if386sx/OKI_IF386SX_even.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_device); + + device_add(&neat_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&if386jega_device); + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_scamp_common_init(const machine_t *model, int is_ps2) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bae9de29f..ce95b5fc8 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4746,6 +4746,44 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { .name = "[NEAT] OKI if386AX30L", + .internal_name = "if386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_if386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .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_VIDEO, + .ram = { + .min = 1024, + .max = 4096, + .step = 1024 + }, + .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 IBM AT KBC firmware. */ { .name = "[OPTi 291] DTK PPM-3333P", diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 438d5c98d..16a3552ad 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -47,9 +47,9 @@ void ega_doblit(int wx, int wy, ega_t *ega); static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static uint8_t ega_rotate[8][256]; -static int active = 0; -static uint32_t pallook16[256]; -static uint32_t pallook64[256]; +static int active = 0; +uint32_t pallook16[256]; +uint32_t pallook64[256]; static int ega_type = EGA_TYPE_IBM; static int old_overscan_color = 0; diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 145579cf5..edf7358a6 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -60,6 +60,7 @@ #define RINVALID_INDEX 0x30 #define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" +#define IF386_PATH_VBIOS "roms/video/jega/OKI_IF386SX_VBIOS.bin" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 @@ -137,7 +138,8 @@ typedef struct { uint16_t end; } fontx_tbl; -static uint32_t pallook64[256]; +extern uint32_t pallook16[256]; +extern uint32_t pallook64[256]; static bool is_SJIS_1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } @@ -615,8 +617,27 @@ LoadFontxFile(const char *fn, void *priv) return 0; } +static void +jega_commoninit(void *priv) +{ + jega_t *jega = (jega_t *) priv; + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + jega->pallook = pallook64; + ega_init(&jega->ega, 9, 0); + ega_set_type(&jega->ega, EGA_SUPEREGA); + jega->ega.priv_parent = jega; + mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); + /* I/O 3DD and 3DE are used by Oki if386 */ + io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + jega->regs[RMOD1] = 0x48; +} + static void * -jega_init(const device_t *info) +jega_standalone_init(const device_t *info) { jega_t *jega = calloc(1, sizeof(jega_t)); @@ -624,21 +645,7 @@ jega_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - for (int c = 0; c < 256; c++) { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); - } - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); - jega->pallook = pallook64; - ega_init(&jega->ega, 9, 0); - ega_set_type(&jega->ega, EGA_SUPEREGA); - jega->ega.priv_parent = jega; - mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); - - io_sethandler(0x03b0, 0x0030, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); - - jega->regs[RMOD1] = 0x48; + jega_commoninit(jega); return jega; } @@ -665,10 +672,10 @@ jega_close(void *priv) fprintf(f, "Regs %02X: %4X\n", i, jega->regs[i]); for (int i = 0; i < 32; i++) fprintf(f, "Attr %02X: %4X\n", i, jega->attrregs[i]); - for (int i = 0; i < 16; i++) - fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]); - for (int i = 0; i < 16; i++) - fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]); for (int i = 0; i < 64; i++) fprintf(f, "RealPal %02X: %4X\n", i, jega->pallook[i]); fclose(f); @@ -683,7 +690,7 @@ jega_close(void *priv) fwrite(&ram[0x0], 0x500, 1, f); fclose(f); } - // jega_log("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); + pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif if (jega->ega.eeprom) free(jega->ega.eeprom); @@ -706,7 +713,7 @@ jega_speed_changed(void *priv) } static int -jega_available(void) +jega_standalone_available(void) { return (rom_present(JEGA_PATH_BIOS) && rom_present(JEGA_PATH_FONTDBCS)); } @@ -716,10 +723,124 @@ const device_t jega_device = { .internal_name = "jega", .flags = DEVICE_ISA, .local = 0, - .init = jega_init, + .init = jega_standalone_init, .close = jega_close, .reset = NULL, - .available = jega_available, + .available = jega_standalone_available, + .speed_changed = jega_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +static uint8_t p65idx = 0; +static uint8_t p3de_idx = 0; +static uint8_t p65[6]; +static uint8_t p3de[0x30]; + + +static uint8_t +if386_p6x_read(uint16_t port, void *priv) +{ + uint8_t ret = INVALIDACCESS8; + if (port == 0x63) { + ret = p65idx; + } else if (port == 0x65) { + ret = p65[p65idx]; + } + // pclog("p%x_r: [%04x:%04x] [%02x]%02x\n", port, cs >> 4, cpu_state.pc , p65idx, ret); + return ret; +} + +/* + OKi if386AX/SX Power management and Miscellaneous + I/O 63h: Index 0-5, I/O 65h: Data + Index 2: + Bit 3: Caps Lock enabled + Bit 2: Num Lock enabled + Bit 1: Scrl Lock enabled + Bit 0: Kana Lock enabled + Index 3 + Bit 2: External monitor output enabled + Bit 1: Floppy drive 1 active + Bit 0: Floppy drive 0 active + Index 5 + Bit 8: ? (1=Disabled, 0=Enabled) + Bit 7: Screen Off? (enabled by Ctrl + Alt + [1] and disabled by any key) + Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21) + Bit 3: ? +*/ +static void +if386_p6x_write(uint16_t port, uint8_t val, void *priv) +{ + jega_t *jega = (jega_t *) priv; + // pclog("p%x_w: [%04x:%04x] val=%02x\n", port, cs >> 4, cpu_state.pc, val); + if (port == 0x63 && val < 6) + p65idx = val; + if (port == 0x65) { + // pclog("p65_w: [%04x:%04x] idx=%02x, val=%02x\n", cs >> 4, cpu_state.pc, p65idx, val); + p65[p65idx] = val; + if (p65idx == 0x03) { + if (val & 0x04) { /* Color monitor */ + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); + if ((c & 0x17) == 6) + pallook16[c] = makecol32(0xaa, 0x55, 0); + } + } else { /* Monochrome LCD */ + for (int c = 0; c < 256; c++) { + int cval = 0; + if (c & 0x0f) + cval = ((c & 0x0e) * 0x10) + 0x1f; + pallook64[c] = makecol32(cval, cval, cval); + pallook16[c] = makecol32(cval, cval, cval); + } + } + jega_recalctimings(jega); + } else if (p65idx == 0x05) { + if (val & 0x10) { /* Power off (instead this call hardware reset here) */ + resetx86(); + } + } + } + return; +} + +static void * +if386jega_init(const device_t *info) +{ + jega_t *jega = calloc(1, sizeof(jega_t)); + + rom_init(&jega->bios_rom, IF386_PATH_VBIOS, 0xc0000, 0x8000, 0x7fff, 0, 0); + memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); + LoadFontxFile(JEGA_PATH_FONTDBCS, jega); + + jega_commoninit(jega); + + io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + // io_sethandler(0x03dd, 2, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + + return jega; +} + +static int +if386jega_available(void) +{ + return (rom_present(IF386_PATH_VBIOS) && rom_present(JEGA_PATH_FONTDBCS)); +} + +const device_t if386jega_device = { + .name = "JEGA (if386AX)", + .internal_name = "if386jega", + .flags = DEVICE_ISA, + .local = 0, + .init = if386jega_init, + .close = jega_close, + .reset = NULL, + .available = if386jega_available, .speed_changed = jega_speed_changed, .force_redraw = NULL, .config = NULL From fe0c246bd2e1bd97dce427e873b896cc8fbc6227 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 01:33:58 +0900 Subject: [PATCH 091/158] if386sx: change rom file path --- src/video/vid_jega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index edf7358a6..f9bcb6918 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -60,8 +60,8 @@ #define RINVALID_INDEX 0x30 #define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" -#define IF386_PATH_VBIOS "roms/video/jega/OKI_IF386SX_VBIOS.bin" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" +#define IF386_PATH_VBIOS "roms/machines/if386sx/OKI_IF386SX_VBIOS.bin" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 #define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2) From 861d942657dc5f8484f5ed2fad331c1687737346 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 11:03:04 +0900 Subject: [PATCH 092/158] Adding skeleton that at least compiles for audio4.c --- CMakeLists.txt | 4 ++++ src/sound/CMakeLists.txt | 5 +++- src/sound/audio4.c | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/sound/audio4.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fb71553e2..55cbec8b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,10 @@ else() option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) endif() +if((CMAKE_SYSTEM_NAME STREQUAL "NetBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) + set(AUDIO4 ON) +endif() + if(WIN32) set(QT ON) option(CPPTHREADS "C++11 threads" OFF) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index a381051ba..955e96f5a 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -53,7 +53,10 @@ add_library(snd OBJECT snd_opl_esfm.c ) -if(OPENAL) +# TODO: Should platform-specific audio driver be here? +if(AUDIO4) + target_sources(snd PRIVATE audio4.c) +elseif(OPENAL) if(VCPKG_TOOLCHAIN) find_package(OpenAL CONFIG REQUIRED) elseif(MINGW) diff --git a/src/sound/audio4.c b/src/sound/audio4.c new file mode 100644 index 000000000..3b3d4a429 --- /dev/null +++ b/src/sound/audio4.c @@ -0,0 +1,51 @@ +/* + * 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. + * + * Interface to audio(4). + * + * + * + * Authors: Nishi + * + * Copyright 2025 Nishi. + */ +#include + +#include <86box/sound.h> + +#define FREQ SOUND_FREQ +#define BUFLEN SOUNDBUFLEN + +static int midi_freq = 44100; +static int midi_buf_size = 4410; + +void closeal(void){ +} + +void inital(void){ +} + +void givealbuffer(const void *buf){ +} + +void givealbuffer_music(const void *buf){ +} + +void givealbuffer_wt(const void *buf){ +} + +void givealbuffer_cd(const void *buf){ +} + +void givealbuffer_midi(const void *buf, const uint32_t size){ +} + +void al_set_midi(const int freq, const int buf_size){ + midi_freq = freq; + midi_buf_size = buf_size; +} From 56d0cbb09336f3f426b5c72c945b39cf0fd4c393 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Mar 2025 06:32:02 +0100 Subject: [PATCH 093/158] Different CPU's for the two V-Tech machines. --- src/machine/machine_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bae9de29f..99f6e26a2 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -1760,7 +1760,7 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_8088, + .package = CPU_PKG_8088_VTECH, .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, @@ -2623,7 +2623,7 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_8086, + .package = CPU_PKG_8086_VTECH, .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, From 7056c83bbb7c444fbdb55ea4a51382f77d7faa36 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 17:41:04 +0900 Subject: [PATCH 094/158] Add working NetBSD sound support --- src/sound/audio4.c | 104 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 3b3d4a429..e7b7dcf33 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -6,8 +6,8 @@ * * This file is part of the 86Box distribution. * - * Interface to audio(4). - * + * Interface to audio(4) for NetBSD/OpenBSD. + * TODO: Test on OpenBSD * * * Authors: Nishi @@ -15,37 +15,121 @@ * Copyright 2025 Nishi. */ #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include <86box/86box.h> #include <86box/sound.h> +#include <86box/plat_unused.h> -#define FREQ SOUND_FREQ -#define BUFLEN SOUNDBUFLEN +#define I_NORMAL 0 +#define I_MUSIC 1 +#define I_WT 2 +#define I_CD 3 +#define I_MIDI 4 -static int midi_freq = 44100; -static int midi_buf_size = 4410; +static int audio[5] = {-1, -1, -1, -1, -1}; +static audio_offset_t offset[5]; +static audio_info_t info[5]; +static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; void closeal(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + if(audio[i] != -1){ + close(audio[i]); + } + audio[i] = -1; + } } void inital(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + audio[i] = open("/dev/audio", O_WRONLY); + if(audio[i] != -1){ + AUDIO_INITINFO(&info[i]); +#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) + ioctl(audio[i], AUDIO_GETFORMAT, &info[i]); +#else + ioctl(audio[i], AUDIO_GETINFO, &info[i]); +#endif + info[i].play.channels = 2; + info[i].play.precision = 16; + info[i].play.encoding = AUDIO_ENCODING_SLINEAR; + info[i].hiwat = 5; + info[i].lowat = 3; + ioctl(audio[i], AUDIO_SETINFO, &info[i]); + } + } +} + +void givealbuffer_common(const void *buf, const uint8_t src, const int size){ + const int freq = freqs[src]; + int16_t* output; + int output_size; + int16_t* conv; + int conv_size; + int i; + double gain; + if(audio[src] == -1) return; + + gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); + + if(sound_is_float){ + float* input = (float*)buf; + conv_size = sizeof(int16_t) * size; + conv = malloc(conv_size); + for(i = 0; i < conv_size / sizeof(int16_t); i++){ + conv[i] = 32767 * input[i]; + } + }else{ + conv_size = size * sizeof(int16_t); + conv = malloc(conv_size); + memcpy(conv, buf, conv_size); + } + + output_size = (double)conv_size * info[src].play.sample_rate / freq; + output = malloc(output_size); + + for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ + int ind = i * freq / info[src].play.sample_rate * 2; + output[i * 2 + 0] = conv[ind + 0] * gain; + output[i * 2 + 1] = conv[ind + 1] * gain; + } + + write(audio[src], output, output_size); + + free(conv); + free(output); } void givealbuffer(const void *buf){ + givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1); } void givealbuffer_music(const void *buf){ + givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1); } void givealbuffer_wt(const void *buf){ + givealbuffer_common(buf, I_WT, WTBUFLEN << 1); } void givealbuffer_cd(const void *buf){ + givealbuffer_common(buf, I_CD, CD_BUFLEN << 1); } - void givealbuffer_midi(const void *buf, const uint32_t size){ + givealbuffer_common(buf, I_MIDI, (int) size); } -void al_set_midi(const int freq, const int buf_size){ - midi_freq = freq; - midi_buf_size = buf_size; +void al_set_midi(const int freq, UNUSED(const int buf_size)){ + freqs[I_MIDI] = freq; } From f287ee4fd0f96945c85feb0dd5085ef6129a223e Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:20:05 +0900 Subject: [PATCH 095/158] Check OpenBSD version and use newer API if needed --- src/sound/audio4.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index e7b7dcf33..ebea8a08f 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -29,6 +29,10 @@ #include <86box/sound.h> #include <86box/plat_unused.h> +#if defined(OpenBSD) && OpenBSD >= 201709 +#define USE_NEW_API +#endif + #define I_NORMAL 0 #define I_MUSIC 1 #define I_WT 2 @@ -36,8 +40,11 @@ #define I_MIDI 4 static int audio[5] = {-1, -1, -1, -1, -1}; -static audio_offset_t offset[5]; +#ifdef USE_NEW_API +static struct audio_swpar info[5]; +#else static audio_info_t info[5]; +#endif static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; void closeal(void){ @@ -55,6 +62,14 @@ void inital(void){ for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); if(audio[i] != -1){ +#ifdef USE_NEW_API + AUDIO_INITPAR(&info[i]); + ioctl(audio[i], AUDIO_GETPAR, &info[i]); + info[i].pchan = 2; + info[i].bits = 16; + info[i].bps = 2; + ioctl(audio[i], AUDIO_SETPAR, &info[i]); +#else AUDIO_INITINFO(&info[i]); #if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000) ioctl(audio[i], AUDIO_GETFORMAT, &info[i]); @@ -67,6 +82,7 @@ void inital(void){ info[i].hiwat = 5; info[i].lowat = 3; ioctl(audio[i], AUDIO_SETINFO, &info[i]); +#endif } } } From ad655ab40c3b3d7115ae719cb985fa9333831341 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:55:37 +0900 Subject: [PATCH 096/158] Forgot to add newer API support in conversion part --- src/sound/audio4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index ebea8a08f..18606f9ce 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -112,11 +112,19 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ memcpy(conv, buf, conv_size); } +#ifdef USE_NEW_API + output_size = (double)conv_size * info[src].rate / freq; +#else output_size = (double)conv_size * info[src].play.sample_rate / freq; +#endif output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ +#ifdef USE_NEW_API + int ind = i * freq / info[src].rate * 2; +#else int ind = i * freq / info[src].play.sample_rate * 2; +#endif output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From 090b9d988a3efa0fa256a0c3b0bcb378dc9457f3 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 18:57:36 +0900 Subject: [PATCH 097/158] Include string.h for memory operations --- src/sound/audio4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 18606f9ce..fe1b8192d 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include From 8daed4c70c4c8274d1bb06231443c2c23a994a2a Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:03:36 +0900 Subject: [PATCH 098/158] OpenBSD needs stdarg.h --- src/include/86box/86box.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e8c5fbac9..c58d595c5 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -20,8 +20,8 @@ #ifndef EMU_86BOX_H #define EMU_86BOX_H -#ifdef __NetBSD__ -/* Doesn't compile on NetBSD without this include */ +#if defined(__NetBSD__) || defined(__OpenBSD__) +/* Doesn't compile on NetBSD/OpenBSD without this include */ #include #endif From ef194e003e921edc2879317bbb22ecc662d0b3fc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:29:37 +0900 Subject: [PATCH 099/158] Check /dev/audio0 too --- src/sound/audio4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index fe1b8192d..2458f78c6 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -62,6 +62,7 @@ void inital(void){ int i; for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); + if(audio[i] != -1) audio[i] = open("/dev/audio0", O_WRONLY); if(audio[i] != -1){ #ifdef USE_NEW_API AUDIO_INITPAR(&info[i]); From e023a046bb597f292ab761df2191802474160182 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:37:15 +0900 Subject: [PATCH 100/158] Wrong comparison --- src/sound/audio4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 2458f78c6..fb98594e6 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -62,7 +62,7 @@ void inital(void){ int i; for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = open("/dev/audio", O_WRONLY); - if(audio[i] != -1) audio[i] = open("/dev/audio0", O_WRONLY); + if(audio[i] == -1) audio[i] = open("/dev/audio0", O_WRONLY); if(audio[i] != -1){ #ifdef USE_NEW_API AUDIO_INITPAR(&info[i]); From e4fb39d9441a127ae5fdcbdf571dcb31a06e91bc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:38:49 +0900 Subject: [PATCH 101/158] Remove TODO message --- src/sound/audio4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index fb98594e6..8428b3c93 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -7,7 +7,6 @@ * This file is part of the 86Box distribution. * * Interface to audio(4) for NetBSD/OpenBSD. - * TODO: Test on OpenBSD * * * Authors: Nishi From 3c4e8c9e4a017dbad54ed206c5eae1dafa1f5540 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 19:46:16 +0900 Subject: [PATCH 102/158] PS55DA2: Fix screen size calculation * Fix screen size calculation in recalctimings. * Set the position of underscore by CRTC reg value. * Optimize text drawing function --- src/video/vid_ps55da2.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index db2035717..81fb1601d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -253,7 +253,7 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -// #define ENABLE_DA2_LOG 1 +#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG @@ -1850,12 +1850,13 @@ da2_render_text(da2_t *da2) int fg, bg; uint32_t chr_dbcs; int chr_wide = 0; + int colormode = ((da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80); // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { chr = da2->cram[(da2->ma) & DA2_MASK_CRAM]; attr = da2->cram[(da2->ma + 1) & DA2_MASK_CRAM]; // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* IO 3E8h, Index 1Dh */ + if (colormode) /* IO 3E8h, Index 1Dh */ { /* --Parse attribute byte in color mode-- */ bg = 0; /* bg color is always black (the only way to change background color is programming PAL) */ fg = getPS55ForeColor(attr, da2); @@ -1932,24 +1933,24 @@ da2_render_text(da2_t *da2) chr_wide = 0; } /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ - if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) { /* Underscore only in monochrome mode */ + if (da2->sc == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]]; /* under line (white) */ } /* Column 1 (Vertical Line) */ if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ + p[0] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ } if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */ + p[n] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */ } /* Drawing text cursor */ drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ - fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ + fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); bg = 0; if (attr & 0x04) { /* Color 0 if reverse */ bg = fg; @@ -2048,8 +2049,8 @@ da2_render_textm3(da2_t *da2) drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { // int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - // int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ - // fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + // int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ + // fg = (colormode) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; // bg = 0; // if (attr & 0x04) {/* Color 0 if reverse */ // bg = fg; @@ -2217,10 +2218,10 @@ da2_recalctimings(da2_t *da2) da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; - if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { - da2->hdisp--; - da2->dispend -= 29; - } + da2->hdisp -= da2->crtc[LC_START_H_DISPLAY_ENAB]; + /* In the J-DOS setup, you'll see the blank below the screen. It's NOT a bug. */ + da2->dispend -= da2->crtc[LC_START_V_DISPLAY_ENAB]; + da2->dispend++; da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; From c135dddfa998c66cb71d6fff004b0f6730e94921 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 19:51:45 +0900 Subject: [PATCH 103/158] Use option instead of set in CMake --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55cbec8b0..aafa46b1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,7 +145,9 @@ else() endif() if((CMAKE_SYSTEM_NAME STREQUAL "NetBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) - set(AUDIO4 ON) + option(AUDIO4 "Use audio(4) as sound backend" ON) +else() + set(AUDIO4 OFF) endif() if(WIN32) From abb0670eb06538ee7f836473fc28ebb9e6705920 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:22:38 +0900 Subject: [PATCH 104/158] PS55DA2: remove unused code, update comment --- src/video/vid_ps55da2.c | 56 ++++++----------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 81fb1601d..af8beddb9 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -11,7 +11,6 @@ * Notes: There are some known issues that should be corrected. * - Incorrect foreground text color appears on an active window in OS/2 J1.3. * - Glitches some part of graphics on the Control Panel in OS/2 J2.1 beta. - * - The screen resolution and blanking interval time maybe not correct. * * The code should be tested with following cases. * - Execute MODE 0, 1, 3 and 4 commands in DOS K3.3 to test various video modes. @@ -253,7 +252,7 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG @@ -284,10 +283,8 @@ da2_log(const char *fmt, ...) #endif typedef struct da2_t { - // mem_mapping_t vmapping; mem_mapping_t cmapping; - // uint8_t crtcreg; uint8_t ioctl[16]; uint8_t fctl[32]; uint16_t crtc[128]; @@ -297,7 +294,6 @@ typedef struct da2_t { uint8_t attrc[0x40]; int attraddr, attrff; int attr_palette_enable; - // uint8_t seqregs[64]; int outflipflop; int inflipflop; int iolatch; @@ -312,7 +308,6 @@ typedef struct da2_t { uint32_t gdcla[8]; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; - uint32_t debug_vramold[8]; uint8_t dac_mask, dac_status; int dac_read, dac_write, dac_pos; @@ -335,7 +330,7 @@ typedef struct da2_t { PALETTE vgapal; int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int hdisp, htotal, hdisp_time, rowoffset; int lowres, interlace; int rowcount; double clock; @@ -2190,13 +2185,14 @@ da2_updatevidselector(da2_t *da2) /* INT 10h video modes supported in DOS J4.0 (The DA-2 doesn't have a video BIOS on its card.) Mode Type Colors Text Base Address PELs Render - 3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 725 textm3 + 3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 754 textm3 8 A/N/K 2 80 x 25 E0000h 1040 x 725 text Ah APA 1 78 x 25 A0000h 1024 x 768 color_4bpp Dh APA 16 78 x 25 A0000h 1024 x 768 color_4bpp Eh A/N/K 16 80 x 25 E0000h 1040 x 725 text Fh APA 256 NA A0000h 1024 x 768 color_8bpp 45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp + 46h(undoc) APA 16 ? A0000h 1040 x 768 color_4bpp */ void da2_recalctimings(da2_t *da2) @@ -2218,10 +2214,10 @@ da2_recalctimings(da2_t *da2) da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + /* In the video mode 3, you'll see a blank below the screen. It's NOT a bug. */ da2->hdisp -= da2->crtc[LC_START_H_DISPLAY_ENAB]; - /* In the J-DOS setup, you'll see the blank below the screen. It's NOT a bug. */ da2->dispend -= da2->crtc[LC_START_V_DISPLAY_ENAB]; - da2->dispend++; + da2->dispend += 1; da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; @@ -2247,15 +2243,14 @@ da2_recalctimings(da2_t *da2) if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; - da2->hdisp_old = da2->hdisp; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { da2_log("Set videomode to PS/55 8 bpp graphics.\n"); da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_A000; } else { /* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_A000; da2->render = da2_render_color_4bpp; + da2->vram_display_mask = DA2_MASK_A000; } } else { /* text mode */ @@ -2269,7 +2264,6 @@ da2_recalctimings(da2_t *da2) da2->vram_display_mask = DA2_MASK_CRAM; } da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; da2->char_width = 13; } // if (!da2->scrblank && da2->attr_palette_enable) @@ -2643,9 +2637,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->mmdbg_vidaddr = addr; //} #endif - cycles -= video_timing_write_b; - da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ addr <<= 3; @@ -2686,27 +2678,13 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; else da2->gdcinput[i] = val; - - // for (int i = 0; i < 8; i++) - // da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ da2_gdcropB(addr, bitmask, da2); - // for (int i = 0; i < 8; i++) - // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], bitmask, da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch - ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1:/* equiv to vga write mode 2 */ - // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - // for (int i = 0; i < 8; i++) - // if (da2->planemask & (1 << i)) - // DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2); - // //fprintf(da2->mmdbg_fp, "m1-1"); - // } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); da2_gdcropB(addr, bitmask, da2); - //fprintf(da2->mmdbg_fp, "m1-2"); - // } break; case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2718,7 +2696,6 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2_gdcropB(addr, bitmask, da2); break; } - // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); } else { /* mode 3h text */ cycles -= video_timing_write_b; DA2_vram_w(addr, val, da2); @@ -2742,8 +2719,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) #ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_wW %x %d %d %02x\n", addr, addr % (da2->rowoffset * 2) * 8, addr / (da2->rowoffset * 2), val); - // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - //{ + if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { fprintf(da2->mmdbg_fp, "\nW %x %x ", addr, val); for (int i = 0; i <= 0xb; i++) @@ -2756,7 +2732,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; - //} #endif cycles -= video_timing_write_w; @@ -2764,7 +2739,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); da2->changedvram[addr >> 9] = changeframecount; - // da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) @@ -3025,9 +2999,6 @@ da2_poll(void *priv) da2->cgastat |= 8; x = da2->hdisp; - // if (da2->interlace && !da2->oddeven) da2->lastline++; - // if (da2->interlace && da2->oddeven) da2->firstline--; - wx = x; wy = da2->lastline - da2->firstline; @@ -3044,17 +3015,9 @@ da2_poll(void *priv) changeframecount = da2->interlace ? 3 : 2; da2->vslines = 0; - // if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); - // else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); - // da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; - /* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; - else*/ da2->ma = da2->maback = da2->ma_latch; da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; - - // da2->ma <<= 1; - // da2->maback <<= 1; da2->ca <<= 1; // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF); @@ -3071,9 +3034,6 @@ da2_poll(void *priv) if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } - // printf("2 %i\n",da2_vsyncstart); - // da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); - // da2_log("r"); } static void From 16a6ab3f95b187ca829dd21ffb17d698eaece1dc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:35:41 +0900 Subject: [PATCH 105/158] Fix music frequency conversion bug --- src/sound/audio4.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 8428b3c93..ad8b3ce82 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -96,6 +96,7 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ int conv_size; int i; double gain; + int target_rate; if(audio[src] == -1) return; gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); @@ -114,18 +115,18 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ } #ifdef USE_NEW_API - output_size = (double)conv_size * info[src].rate / freq; + target_rate = info[src].rate; #else - output_size = (double)conv_size * info[src].play.sample_rate / freq; + target_rate = info[src].play.sample_rate; #endif + + output_size = (double)conv_size * target_rate / freq; + output_size -= output_size % 2; output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ -#ifdef USE_NEW_API - int ind = i * freq / info[src].rate * 2; -#else - int ind = i * freq / info[src].play.sample_rate * 2; -#endif + int ind = i * freq / target_rate * 2; + ind -= ind % 2; output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From fefcd530ab86dbb2143e01b8d0ae1117bccf6794 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:37:46 +0900 Subject: [PATCH 106/158] Remove the part that was not required --- src/sound/audio4.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index ad8b3ce82..2bad30144 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -126,7 +126,6 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ int ind = i * freq / target_rate * 2; - ind -= ind % 2; output[i * 2 + 0] = conv[ind + 0] * gain; output[i * 2 + 1] = conv[ind + 1] * gain; } From c92d56261a38aed2e95c1445192763e540a7e244 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 20:44:29 +0900 Subject: [PATCH 107/158] Do mod4 instead of mod2, so it can keep the output channel correct --- src/sound/audio4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 2bad30144..32989eecf 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -121,7 +121,7 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ #endif output_size = (double)conv_size * target_rate / freq; - output_size -= output_size % 2; + output_size -= output_size % 4; output = malloc(output_size); for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ From b4fdb6dcdc1e4bfea8e91411112a869ced350ce6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Mar 2025 14:17:59 +0100 Subject: [PATCH 108/158] Vulkan renderer: Take the dpi_scale option into account when setting up the videwport, fixes #5374. --- src/qt/qt_vulkanrenderer.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/qt/qt_vulkanrenderer.cpp b/src/qt/qt_vulkanrenderer.cpp index 13728b82e..39830569c 100644 --- a/src/qt/qt_vulkanrenderer.cpp +++ b/src/qt/qt_vulkanrenderer.cpp @@ -970,10 +970,17 @@ VulkanRenderer2::startNextFrame() m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset); VkViewport viewport; - viewport.x = destination.x() * m_window->devicePixelRatio(); - viewport.y = destination.y() * m_window->devicePixelRatio(); - viewport.width = destination.width() * m_window->devicePixelRatio(); - viewport.height = destination.height() * m_window->devicePixelRatio(); + if (dpi_scale) { + viewport.x = destination.x() * m_window->devicePixelRatio(); + viewport.y = destination.y() * m_window->devicePixelRatio(); + viewport.width = destination.width() * m_window->devicePixelRatio(); + viewport.height = destination.height() * m_window->devicePixelRatio(); + } else { + viewport.x = destination.x(); + viewport.y = destination.y(); + viewport.width = destination.width(); + viewport.height = destination.height(); + } viewport.minDepth = 0; viewport.maxDepth = 1; m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport); From d361befe757f6dafd2408b0d1c47c6a57c06df0f Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Mar 2025 14:23:38 +0100 Subject: [PATCH 109/158] JEGA: Commented out the two 3de arrays which are currently unused. --- src/video/vid_jega.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index f9bcb6918..4d411c39c 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -733,9 +733,9 @@ const device_t jega_device = { }; static uint8_t p65idx = 0; -static uint8_t p3de_idx = 0; +// static uint8_t p3de_idx = 0; static uint8_t p65[6]; -static uint8_t p3de[0x30]; +// static uint8_t p3de[0x30]; static uint8_t From 9fed70679300260260440492c7f9ae5c92a3551a Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 22:37:39 +0900 Subject: [PATCH 110/158] Add sndio.c that might compile --- CMakeLists.txt | 8 ++- src/sound/CMakeLists.txt | 2 + src/sound/sndio.c | 132 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/sound/sndio.c diff --git a/CMakeLists.txt b/CMakeLists.txt index aafa46b1c..a94321038 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,12 +144,18 @@ else() option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF) endif() -if((CMAKE_SYSTEM_NAME STREQUAL "NetBSD") OR (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) +if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") option(AUDIO4 "Use audio(4) as sound backend" ON) else() set(AUDIO4 OFF) endif() +if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + option(SNDIO "Use sndio as sound backend" ON) +else() + set(SNDIO OFF) +endif() + if(WIN32) set(QT ON) option(CPPTHREADS "C++11 threads" OFF) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 955e96f5a..0f96aa9a6 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -56,6 +56,8 @@ add_library(snd OBJECT # TODO: Should platform-specific audio driver be here? if(AUDIO4) target_sources(snd PRIVATE audio4.c) +elseif(SNDIO) + target_sources(snd PRIVATE sndio.c) elseif(OPENAL) if(VCPKG_TOOLCHAIN) find_package(OpenAL CONFIG REQUIRED) diff --git a/src/sound/sndio.c b/src/sound/sndio.c new file mode 100644 index 000000000..bb483d9fe --- /dev/null +++ b/src/sound/sndio.c @@ -0,0 +1,132 @@ +/* + * 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. + * + * Interface to audio(4) for NetBSD/OpenBSD. + * + * + * Authors: Nishi + * + * Copyright 2025 Nishi. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include <86box/86box.h> +#include <86box/sound.h> +#include <86box/plat_unused.h> + +#define I_NORMAL 0 +#define I_MUSIC 1 +#define I_WT 2 +#define I_CD 3 +#define I_MIDI 4 + +static struct sio_hdl* audio[5] = {NULL, NULL, NULL, NULL, NULL}; +static struct sio_par info[5]; +static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; + +void closeal(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + if(audio[i] != NULL){ + sio_close(audio[i]); + } + audio[i] = NULL; + } +} + +void inital(void){ + int i; + for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ + audio[i] = sio_open(SIO_DEVANY, SIO_PLAY, 0); + if(audio[i] != NULL){ + sio_initpar(&info[i]); + sio_getpar(audio[i], &info[i]); + info[i].sig = 1; + info[i].bits = 16; + info[i].pchan = 2; + sio_setpar(audio[i], &info[i]); + sio_start(audio[i]); + } + } +} + +void givealbuffer_common(const void *buf, const uint8_t src, const int size){ + const int freq = freqs[src]; + int16_t* output; + int output_size; + int16_t* conv; + int conv_size; + int i; + double gain; + int target_rate; + if(audio[src] == -1) return; + + gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); + + if(sound_is_float){ + float* input = (float*)buf; + conv_size = sizeof(int16_t) * size; + conv = malloc(conv_size); + for(i = 0; i < conv_size / sizeof(int16_t); i++){ + conv[i] = 32767 * input[i]; + } + }else{ + conv_size = size * sizeof(int16_t); + conv = malloc(conv_size); + memcpy(conv, buf, conv_size); + } + + target_rate = info[src].rate; + + output_size = (double)conv_size * target_rate / freq; + output_size -= output_size % 4; + output = malloc(output_size); + + for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){ + int ind = i * freq / target_rate * 2; + output[i * 2 + 0] = conv[ind + 0] * gain; + output[i * 2 + 1] = conv[ind + 1] * gain; + } + + sio_write(audio[src], output, output_size); + + free(conv); + free(output); +} + +void givealbuffer(const void *buf){ + givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1); +} + +void givealbuffer_music(const void *buf){ + givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1); +} + +void givealbuffer_wt(const void *buf){ + givealbuffer_common(buf, I_WT, WTBUFLEN << 1); +} + +void givealbuffer_cd(const void *buf){ + givealbuffer_common(buf, I_CD, CD_BUFLEN << 1); +} +void givealbuffer_midi(const void *buf, const uint32_t size){ + givealbuffer_common(buf, I_MIDI, (int) size); +} + +void al_set_midi(const int freq, UNUSED(const int buf_size)){ + freqs[I_MIDI] = freq; +} From 277b422940fa953246cd28c054da73fce40cc596 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 22:41:43 +0900 Subject: [PATCH 111/158] Forgot to add linking/including stuff to CMake --- src/sound/CMakeLists.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 0f96aa9a6..b2cbb57f0 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -58,6 +58,20 @@ if(AUDIO4) target_sources(snd PRIVATE audio4.c) elseif(SNDIO) target_sources(snd PRIVATE sndio.c) + find_package(PkgConfig REQUIRED) + + # Use FAudio, a reimplementation of XAudio2 + pkg_check_modules(SNDIO IMPORTED_TARGET sndio) + if(SNDIO_FOUND) + target_link_libraries(86Box PkgConfig::SNDIO) + else() + find_path(SNDIO_INCLUDE_DIR NAMES "sndio.h") + find_library(SNDIO_LIBRARY sndio) + + target_link_libraries(86Box ${SNDIO_LIBRARY}) + endif() + + include_directories(${SNDIO_INCLUDE_DIRS}) elseif(OPENAL) if(VCPKG_TOOLCHAIN) find_package(OpenAL CONFIG REQUIRED) From 251dcacaa162099027b7684d3ab57faaa598c9fc Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 22:44:28 +0900 Subject: [PATCH 112/158] fix include --- src/sound/sndio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sound/sndio.c b/src/sound/sndio.c index bb483d9fe..2a454f5fc 100644 --- a/src/sound/sndio.c +++ b/src/sound/sndio.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Interface to audio(4) for NetBSD/OpenBSD. + * Interface to sndio * * * Authors: Nishi @@ -14,15 +14,13 @@ * Copyright 2025 Nishi. */ #include -#include #include -#include #include #include #include #include -#include +#include #include <86box/86box.h> #include <86box/sound.h> From 5de2d6b86dcba49db57039f4ce2d10f68f4004e2 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 22:45:11 +0900 Subject: [PATCH 113/158] Should be NULL not -1 --- src/sound/sndio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/sndio.c b/src/sound/sndio.c index 2a454f5fc..56f8ec8cf 100644 --- a/src/sound/sndio.c +++ b/src/sound/sndio.c @@ -71,7 +71,7 @@ void givealbuffer_common(const void *buf, const uint8_t src, const int size){ int i; double gain; int target_rate; - if(audio[src] == -1) return; + if(audio[src] == NULL) return; gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); From 6e83a7fc96ea44acf9dea93d2f4752043c4cadba Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Mar 2025 23:30:13 +0900 Subject: [PATCH 114/158] Get sio_par for safety --- src/sound/audio4.c | 3 ++- src/sound/sndio.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 32989eecf..4e74d2c0c 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -66,8 +66,9 @@ void inital(void){ #ifdef USE_NEW_API AUDIO_INITPAR(&info[i]); ioctl(audio[i], AUDIO_GETPAR, &info[i]); - info[i].pchan = 2; + info[i].sig = 1; info[i].bits = 16; + info[i].pchan = 2; info[i].bps = 2; ioctl(audio[i], AUDIO_SETPAR, &info[i]); #else diff --git a/src/sound/sndio.c b/src/sound/sndio.c index 56f8ec8cf..5c3adad49 100644 --- a/src/sound/sndio.c +++ b/src/sound/sndio.c @@ -57,6 +57,7 @@ void inital(void){ info[i].bits = 16; info[i].pchan = 2; sio_setpar(audio[i], &info[i]); + sio_getpar(audio[i], &info[i]); sio_start(audio[i]); } } From 1ef20bea361494e14960f3cb934c3b2e3f90b46b Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 25 Mar 2025 00:01:15 +0900 Subject: [PATCH 115/158] Had to assign some values --- src/sound/sndio.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sound/sndio.c b/src/sound/sndio.c index 5c3adad49..2fe1434df 100644 --- a/src/sound/sndio.c +++ b/src/sound/sndio.c @@ -51,14 +51,23 @@ void inital(void){ for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){ audio[i] = sio_open(SIO_DEVANY, SIO_PLAY, 0); if(audio[i] != NULL){ - sio_initpar(&info[i]); + int rate; + int max_frames; sio_getpar(audio[i], &info[i]); + rate = info[i].rate; + max_frames = info[i].bufsz; + sio_initpar(&info[i]); info[i].sig = 1; info[i].bits = 16; info[i].pchan = 2; + info[i].rate = rate; + info[i].appbufsz = max_frames; sio_setpar(audio[i], &info[i]); sio_getpar(audio[i], &info[i]); - sio_start(audio[i]); + if(!sio_start(audio[i])){ + sio_close(audio[i]); + audio[i] = NULL; + } } } } From d68a56a3c92c40c279c89bcdc69c0e1ce00c2538 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 25 Mar 2025 00:52:27 +0900 Subject: [PATCH 116/158] Forgot to remove the comment --- src/sound/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index b2cbb57f0..0a04b0ff1 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -60,7 +60,6 @@ elseif(SNDIO) target_sources(snd PRIVATE sndio.c) find_package(PkgConfig REQUIRED) - # Use FAudio, a reimplementation of XAudio2 pkg_check_modules(SNDIO IMPORTED_TARGET sndio) if(SNDIO_FOUND) target_link_libraries(86Box PkgConfig::SNDIO) From c7b5aa8f0421f3d064b23b1b3d2c924a1a3747c7 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 24 Mar 2025 18:51:28 +0100 Subject: [PATCH 117/158] DEC 21x4 changes of the day (March 24th, 2025) 1. Change the block type of the extended format of the 21143 to 3 and do not issue an IRQ abuse. --- src/network/net_tulip.c | 50 ++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 7d988368c..685873c93 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -971,7 +971,8 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) case CSR(7): s->csr[7] = data; - tulip_update_int(s); + if (s->device_info->local) + tulip_update_int(s); break; case CSR(8): @@ -1006,7 +1007,7 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque) case CSR(13): s->csr[13] = data; - if (s->device_info->local == 3 && (data & 0x4)) { + if ((s->device_info->local == 3) && (data & 0x4)) { s->csr[13] = 0x8f01; s->csr[14] = 0xfffd; s->csr[15] = 0; @@ -1407,7 +1408,7 @@ nic_init(const device_t *info) if (!s) return NULL; - if (info->local && info->local != 3) { + if (info->local && (info->local != 3)) { s->bios_addr = 0xD0000; s->has_bios = device_get_config_int("bios"); } else { @@ -1434,7 +1435,7 @@ nic_init(const device_t *info) s->eeprom_data[2] = 0x14; s->eeprom_data[3] = 0x21; } else { - /*Subsystem Vendor ID*/ + /*Subsystem Vendor ID*/ s->eeprom_data[0] = info->local ? 0x25 : 0x11; s->eeprom_data[1] = 0x10; @@ -1549,23 +1550,40 @@ nic_init(const device_t *info) /*Block Count*/ s->eeprom_data[32] = 0x01; - /*Extended Format - Block Type 2 for 21142/21143*/ + /*Extended Format - Block Type 3 for 21142/21143*/ /*Length (0:6) and Format Indicator (7)*/ - s->eeprom_data[33] = 0x86; + s->eeprom_data[33] = 0x8d; /*Block Type*/ - s->eeprom_data[34] = 0x02; + s->eeprom_data[34] = 0x03; - /*Media Code (0:5), EXT (6), Reserved (7)*/ - s->eeprom_data[35] = 0x01; + /*PHY Number*/ + s->eeprom_data[35] = 0x00; - /*General Purpose Control*/ - s->eeprom_data[36] = 0xff; - s->eeprom_data[37] = 0xff; + /*GPR Length*/ + s->eeprom_data[36] = 0x00; - /*General Purpose Data*/ + /*Reset Length*/ + s->eeprom_data[37] = 0x00; + + /*Media Capabilities*/ s->eeprom_data[38] = 0x00; - s->eeprom_data[39] = 0x00; + s->eeprom_data[39] = 0x78; + + /*Nway Advertisement*/ + s->eeprom_data[40] = 0xe0; + s->eeprom_data[41] = 0x01; + + /*FDX Bit Map*/ + s->eeprom_data[42] = 0x00; + s->eeprom_data[43] = 0x50; + + /*TTM Bit Map*/ + s->eeprom_data[44] = 0x00; + s->eeprom_data[45] = 0x18; + + /*MII PHY Insertion/removal Indication*/ + s->eeprom_data[46] = 0x00; } s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff; @@ -1608,7 +1626,7 @@ nic_init(const device_t *info) checksum *= 2; if (checksum > 65535) checksum = checksum % 65535; - + /* 3rd pair. */ checksum += (s->eeprom_data[4] * 256) | s->eeprom_data[5]; if (checksum > 65535) @@ -1616,7 +1634,7 @@ nic_init(const device_t *info) if (checksum >= 65535) checksum = 0; - + s->eeprom_data[6] = (checksum >> 8) & 0xFF; s->eeprom_data[7] = checksum & 0xFF; } From d91cc459bf52fbc07fe864f67d234ed059ae45be Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 24 Mar 2025 19:02:46 +0100 Subject: [PATCH 118/158] OKI IF386AX: Implement the NEATsx chipset and give it the AT Phoenix keyboard controller. --- src/chipset/neat.c | 144 ++++++++++++++++++++++++----------- src/device/kbc_at.c | 40 ++++++++-- src/include/86box/chipset.h | 1 + src/include/86box/keyboard.h | 1 + src/include/86box/machine.h | 2 + src/machine/m_at_286_386sx.c | 4 +- src/machine/machine_table.c | 12 +-- 7 files changed, 146 insertions(+), 58 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index d4eb3ec7f..f6a7fafb2 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -53,6 +53,7 @@ #define REG_RA1 0x61 /* Command Delay */ #define RA1_MASK 0xff /* 1111 1111 */ +#define RA1_MASK_SX 0xbf /* 1X11 1111 */ #define RA1_BUSDLY 0x03 /* AT BUS command delay */ #define RA1_BUSDLY_SH 0 #define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */ @@ -81,6 +82,7 @@ #define ATWS_3 1 /* 3 wait states */ #define ATWS_4 2 /* 4 wait states */ #define ATWS_5 4 /* 5 wait states */ +#define RA2_387SX 0x80 /* CS8221 82C212 controller registers. */ #define REG_RB0 0x64 /* Version ID */ @@ -103,6 +105,9 @@ #define REG_RB2 0x66 /* Memory Enable 1 */ #define RB2_MASK 0x80 /* 1XXX XXXX */ +#define RB2_MASK_SX 0xe0 /* 111X XXXX */ +#define RB2_BOT256 0x20 /* bottom 256K is on sysboard (1) */ +#define RB2_MID256 0x40 /* middle 256K is on sysboard (1) */ #define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */ #define REG_RB3 0x67 /* Memory Enable 2 */ @@ -198,6 +203,7 @@ #define REG_RB12 0x6f /* Miscellaneous */ #define RB12_MASK 0xe6 /* 111R R11R */ +#define RB12_MASK_SX 0xf6 /* 1111 R11R */ #define RB12_GA20 0x02 /* gate for A20 */ #define RB12_RASTMO 0x04 /* enable RAS timeout counter */ #define RB12_EMSLEN 0xe0 /* EMS memory chunk size */ @@ -221,11 +227,10 @@ typedef struct ram_page_t { } ram_page_t; typedef struct neat_t { - uint8_t mem_flags[32]; + uint8_t mem_flags[64]; uint8_t regs[128]; /* all the CS8221 registers */ uint8_t indx; /* programmed index into registers */ - - char pad; + uint8_t sx; uint16_t ems_base; /* configured base address */ uint32_t ems_frame; /* configured frame address */ @@ -238,8 +243,19 @@ typedef struct neat_t { ram_page_t shadow[32]; /* Shadow RAM pages */ } neat_t; -static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 }; +static uint8_t defaults[2][16] = { { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x43, 0x10, 0x00, 0x00, 0x12 }, + { 0x0a, 0x45, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x00, 0x08 } }; + +static uint8_t reg_masks[2][16] = { { RA0_MASK, RA1_MASK, RA2_MASK, 0x00, + RB0_MASK, RB1_MASK, RB2_MASK, RB3_MASK, + RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK, + RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK }, + { RA0_MASK, RA1_MASK_SX, RA2_MASK, 0x00, + RB0_MASK, RB1_MASK, RB2_MASK_SX, RB3_MASK, + RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK, + RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK_SX } }; static uint8_t masks[4] = { RB10_P0EXT, RB10_P1EXT, RB10_P2EXT, RB10_P3EXT }; static uint8_t shifts[4] = { RB10_P0EXT_SH, RB10_P1EXT_SH, RB10_P2EXT_SH, RB10_P3EXT_SH }; @@ -405,12 +421,12 @@ ems_writew(uint32_t addr, uint16_t val, void *priv) static void neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask) { - if ((addr >= 0x00080000) && (addr < 0x00100000) && - ((new_flags ^ dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) { - dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask; - dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags; + if ((addr < 0x00100000) && + ((new_flags ^ dev->mem_flags[addr / EMS_PGSIZE]) & mask)) { + dev->mem_flags[addr / EMS_PGSIZE] &= ~mask; + dev->mem_flags[addr / EMS_PGSIZE] |= new_flags; - new_flags = dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE]; + new_flags = dev->mem_flags[addr / EMS_PGSIZE]; if (new_flags & MEM_FLAG_ROMCS) { neat_log("neat_mem_update_state(): %08X-%08X: %02X (ROMCS)\n", addr, addr + size - 1, new_flags); @@ -691,6 +707,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) uint8_t xval; uint8_t j; uint8_t *reg; + uint8_t mask; int i; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) @@ -705,10 +722,11 @@ neat_write(uint16_t port, uint8_t val, void *priv) case 0x23: reg = &dev->regs[dev->indx]; xval = *reg ^ val; + mask = reg_masks[dev->sx][dev->indx & REG_MASK]; switch (dev->indx) { case REG_RA0: - val &= RA0_MASK; - *reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH); + val &= mask; + *reg = (*reg & ~mask) | val | (RA0_REV_ID << RA0_REV_SH); if ((xval & 0x20) && (val & 0x20)) outb(0x64, 0xfe); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) @@ -717,32 +735,32 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RA1: - val &= RA1_MASK; - *reg = (*reg & ~RA1_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg); #endif break; case REG_RA2: - val &= RA2_MASK; - *reg = (*reg & ~RA2_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg); #endif break; case REG_RB0: - val &= RB0_MASK; - *reg = (*reg & ~RB0_MASK) | val | (RB0_REV_ID << RB0_REV_SH); + val &= mask; + *reg = (*reg & ~mask) | val | (RB0_REV_ID << RB0_REV_SH); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg); #endif break; case REG_RB1: - val &= RB1_MASK; - *reg = (*reg & ~RB1_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; shadow_recalc(dev); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg); @@ -750,20 +768,37 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB2: - val &= RB2_MASK; - *reg = (*reg & ~RB2_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; + if (dev->sx) { + if (val & RB2_BOT256) + neat_mem_update_state(dev, 0x00000000, 0x00040000, + MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW); + else + neat_mem_update_state(dev, 0x00000000, 0x00040000, + 0x00, MEM_FMASK_SHADOW); + + if (val & RB2_MID256) + neat_mem_update_state(dev, 0x00040000, 0x00040000, + MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW); + else + neat_mem_update_state(dev, 0x00040000, 0x00040000, + 0x00, MEM_FMASK_SHADOW); + } if (val & RB2_TOP128) - neat_mem_update_state(dev, 0x00080000, 0x00020000, MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW); + neat_mem_update_state(dev, 0x00080000, 0x00020000, + MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW); else - neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, MEM_FMASK_SHADOW); + neat_mem_update_state(dev, 0x00080000, 0x00020000, + 0x00, MEM_FMASK_SHADOW); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg); #endif break; case REG_RB3: - val &= RB3_MASK; - *reg = (*reg & ~RB3_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; shadow_recalc(dev); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg); @@ -771,8 +806,8 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB4: - val &= RB4_MASK; - *reg = (*reg & ~RB4_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; shadow_recalc(dev); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg); @@ -780,8 +815,8 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB5: - val &= RB5_MASK; - *reg = (*reg & ~RB5_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; shadow_recalc(dev); #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg); @@ -789,20 +824,20 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB6: - val &= RB6_MASK; - *reg = (*reg & ~RB6_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg); #endif break; case REG_RB7: - val &= RB7_MASK; + val &= mask; if (xval & (RB7_EMSEN | RB7_UMAREL)) remap_update(dev, val); - dev->regs[REG_RB7] = val; + *reg = (*reg & ~mask) | val; if (xval & RB7_EMSEN) ems_remove_handlers(dev); @@ -816,16 +851,16 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB8: - val &= RB8_MASK; - *reg = (*reg & ~RB8_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg); #endif break; case REG_RB9: - val &= RB9_MASK; - *reg = (*reg & ~RB9_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg); #endif @@ -847,8 +882,8 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB10: - val &= RB10_MASK; - *reg = (*reg & ~RB10_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg); #endif @@ -882,8 +917,8 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; case REG_RB12: - val &= RB12_MASK; - *reg = (*reg & ~RB12_MASK) | val; + val &= mask; + *reg = (*reg & ~mask) | val; #if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2) neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg); #endif @@ -976,6 +1011,8 @@ neat_init(UNUSED(const device_t *info)) /* Create an instance. */ dev = (neat_t *) calloc(1, sizeof(neat_t)); + dev->sx = info->local; + if (mem_size > 1024) { mem_mapping_set_handler(&ram_high_mapping, neat_read_ram, neat_read_ramw, NULL, neat_write_ram, neat_write_ramw, NULL); @@ -1002,7 +1039,7 @@ neat_init(UNUSED(const device_t *info)) neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_SHADOW); else { /* This is needed to actually trigger an update. */ - dev->mem_flags[i + 8] = MEM_FLAG_ROMCS; + dev->mem_flags[i + 40] = MEM_FLAG_ROMCS; neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_SHADOW); } } @@ -1045,7 +1082,10 @@ neat_init(UNUSED(const device_t *info)) /* Initialize some of the registers to specific defaults. */ for (uint8_t i = REG_RA0; i <= REG_RB12; i++) { dev->indx = i; - neat_write(0x0023, defaults[i & REG_MASK], dev); + uint8_t def = defaults[dev->sx][i & REG_MASK]; + if ((i == REG_RA2) && (fpu_type == FPU_387)) + def |= RA2_387SX; + neat_write(0x0023, def, dev); } /* @@ -1190,7 +1230,7 @@ neat_init(UNUSED(const device_t *info)) } const device_t neat_device = { - .name = "C&T CS8121 (NEAT)", + .name = "C&T CS8221 (NEAT)", .internal_name = "neat", .flags = 0, .local = 0, @@ -1202,3 +1242,17 @@ const device_t neat_device = { .force_redraw = NULL, .config = NULL }; + +const device_t neat_sx_device = { + .name = "C&T CS8281 (NEATsx)", + .internal_name = "neat_sx", + .flags = 0, + .local = 1, + .init = neat_init, + .close = neat_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 09855a387..abb10d108 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -1577,21 +1577,35 @@ write64_phoenix(void *priv, uint8_t val) revision level and proper CPU bits. */ case 0xd5: /* Read MultiKey code revision level */ kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n"); - kbc_at_queue_add(dev, 0x04); - kbc_at_queue_add(dev, 0x16); + if (dev->misc_flags & FLAG_PS2) { + kbc_at_queue_add(dev, 0x04); + kbc_at_queue_add(dev, 0x16); + } else { + kbc_at_queue_add(dev, 0x01); + kbc_at_queue_add(dev, 0x29); + } return 0; case 0xd6: /* Read Version Information */ kbc_at_log("ATkbc: Phoenix - Read Version Information\n"); kbc_at_queue_add(dev, 0x81); - kbc_at_queue_add(dev, 0xac); + if (dev->misc_flags & FLAG_PS2) + kbc_at_queue_add(dev, 0xac); + else + kbc_at_queue_add(dev, 0xaa); return 0; case 0xd7: /* Read MultiKey model numbers */ kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n"); - kbc_at_queue_add(dev, 0x02); - kbc_at_queue_add(dev, 0x87); - kbc_at_queue_add(dev, 0x02); + if (dev->misc_flags & FLAG_PS2) { + kbc_at_queue_add(dev, 0x02); + kbc_at_queue_add(dev, 0x87); + kbc_at_queue_add(dev, 0x02); + } else { + kbc_at_queue_add(dev, 0x90); + kbc_at_queue_add(dev, 0x88); + kbc_at_queue_add(dev, 0xd0); + } return 0; default: @@ -2510,6 +2524,20 @@ const device_t keyboard_at_compaq_device = { .config = NULL }; +const device_t keyboard_at_phoenix_device = { + .name = "PC/AT Keyboard (Phoenix)", + .internal_name = "keyboard_at_phoenix", + .flags = DEVICE_KBC, + .local = KBC_TYPE_ISA | KBC_VEN_PHOENIX, + .init = kbc_at_init, + .close = kbc_at_close, + .reset = kbc_at_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t keyboard_ps2_device = { .name = "PS/2 Keyboard", .internal_name = "keyboard_ps2", diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index e47bb489f..3a65bbce9 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -48,6 +48,7 @@ extern const device_t contaq_82c597_device; /* C&T */ extern const device_t ct_82c100_device; extern const device_t neat_device; +extern const device_t neat_sx_device; extern const device_t scat_device; extern const device_t scat_4_device; extern const device_t scat_sx_device; diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 3a7260c72..9142fbfe1 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -234,6 +234,7 @@ extern const device_t keyboard_xtclone_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; extern const device_t keyboard_at_compaq_device; +extern const device_t keyboard_at_phoenix_device; extern const device_t keyboard_at_ncr_device; extern const device_t keyboard_at_olivetti_device; extern const device_t keyboard_at_siemens_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 21e4a89e2..16ccb2720 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -208,7 +208,9 @@ enum { MACHINE_CHIPSET_ALI_ALADDIN_V, MACHINE_CHIPSET_ALI_ALADDIN_PRO_II, MACHINE_CHIPSET_SCAT, + MACHINE_CHIPSET_SCAT_SX, MACHINE_CHIPSET_NEAT, + MACHINE_CHIPSET_NEAT_SX, MACHINE_CHIPSET_CT_386, MACHINE_CHIPSET_CT_CS4031, MACHINE_CHIPSET_CONTAQ_82C596, diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 2f35427be..136922a5c 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -654,9 +654,9 @@ machine_at_if386sx_init(const machine_t *model) return ret; machine_at_common_init(model); - device_add(&keyboard_at_device); + device_add(&keyboard_at_phoenix_device); - device_add(&neat_device); + device_add(&neat_sx_device); if (gfxcard[0] == VID_INTERNAL) device_add(&if386jega_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b78c11ec8..f3d39833e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -115,7 +115,9 @@ const machine_filter_t machine_chipsets[] = { { "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V }, { "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II }, { "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT }, - { "C&T CS8121 NEAT", MACHINE_CHIPSET_NEAT }, + { "C&T 82C236 SCATsx", MACHINE_CHIPSET_SCAT_SX }, + { "C&T CS8221 NEAT", MACHINE_CHIPSET_NEAT }, + { "C&T CS8281 NEATsx", MACHINE_CHIPSET_NEAT_SX }, { "C&T 386", MACHINE_CHIPSET_CT_386 }, { "C&T CS4031", MACHINE_CHIPSET_CT_CS4031 }, { "Contaq 82C596", MACHINE_CHIPSET_CONTAQ_82C596 }, @@ -4746,10 +4748,10 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - { .name = "[NEAT] OKI if386AX30L", + { .name = "[NEATsx] OKI if386AX30L", .internal_name = "if386sx", .type = MACHINE_TYPE_386SX, - .chipset = MACHINE_CHIPSET_NEAT, + .chipset = MACHINE_CHIPSET_NEAT_SX, .init = machine_at_if386sx_init, .p1_handler = NULL, .gpio_handler = NULL, @@ -4951,10 +4953,10 @@ const machine_t machines[] = { /* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a photo or real hardware BIOS string is found. */ { - .name = "[SCAT] Kaimei KMX-C-02", + .name = "[SCATsx] Kaimei KMX-C-02", .internal_name = "kmxc02", .type = MACHINE_TYPE_386SX, - .chipset = MACHINE_CHIPSET_SCAT, + .chipset = MACHINE_CHIPSET_SCAT_SX, .init = machine_at_kmxc02_init, .p1_handler = NULL, .gpio_handler = NULL, From db6e74a3b9a94083fd47cada3b8a3325ad48dd06 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 01:47:34 +0100 Subject: [PATCH 119/158] NEAT/NEATsx: Fix the EMS enabled condition in the RAM remapping function, fixes 386 enhanced mode operations on the OKI IF386AX. --- src/chipset/neat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index f6a7fafb2..ffc25d6d9 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -686,9 +686,10 @@ remap_update(neat_t *dev, uint8_t val) mem_mapping_set_addr(&ram_low_mapping, 0x00000000, dev->remap_base << 10); if (dev->remap_base > 1024) { - mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (dev->remap_base << 10) - 0x00100000); - mem_mapping_set_exec(&ram_high_mapping, &(ram[(val & RB7_EMSEN) ? 0x00100000 : - (0x00100000 + (dev->ems_size << 10))])); + uint32_t base = (val & RB7_EMSEN) ? (0x00100000 + (dev->ems_size << 10)) : 0x00100000; + + mem_mapping_set_addr(&ram_high_mapping, base, (dev->remap_base << 10) - 0x00100000); + mem_mapping_set_exec(&ram_high_mapping, &(ram[base])); } else mem_mapping_disable(&ram_high_mapping); From 3f6593f314f47607771395064e23b8bd3f4c3ed5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 02:02:00 +0100 Subject: [PATCH 120/158] IF386AX: Set video card to fixed and make the power off function actually power off. --- src/machine/m_at_286_386sx.c | 4 ++-- src/machine/machine_table.c | 2 +- src/video/vid_jega.c | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 136922a5c..033233955 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -658,8 +658,8 @@ machine_at_if386sx_init(const machine_t *model) device_add(&neat_sx_device); - if (gfxcard[0] == VID_INTERNAL) - device_add(&if386jega_device); + device_add(&if386jega_device); + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index f3d39833e..9f2d0ce47 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4768,7 +4768,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_AT, - .flags = MACHINE_VIDEO, + .flags = MACHINE_VIDEO_FIXED, .ram = { .min = 1024, .max = 4096, diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 4d411c39c..4730b5142 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -28,6 +28,7 @@ #include <86box/timer.h> #include <86box/pic.h> #include <86box/pit.h> +#include <86box/plat.h> #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> @@ -800,9 +801,11 @@ if386_p6x_write(uint16_t port, uint8_t val, void *priv) } jega_recalctimings(jega); } else if (p65idx == 0x05) { - if (val & 0x10) { /* Power off (instead this call hardware reset here) */ - resetx86(); - } + if (val & 0x10) + /* Power off (instead this call hardware reset here) */ + // resetx86(); + /* Actually, power off - we have a function for that! */ + plat_power_off(); } } return; From 260f91313a574a0d1f1254cb6252b4d6d3c76daf Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 02:08:35 +0100 Subject: [PATCH 121/158] JEGA: Bring back the reset for time being, the BIOS needs it to reboot. --- src/video/vid_jega.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 4730b5142..36cf04077 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -803,9 +803,9 @@ if386_p6x_write(uint16_t port, uint8_t val, void *priv) } else if (p65idx == 0x05) { if (val & 0x10) /* Power off (instead this call hardware reset here) */ - // resetx86(); + resetx86(); /* Actually, power off - we have a function for that! */ - plat_power_off(); + // plat_power_off(); } } return; From e71c30ce8457fae5dd3910780e64cca56d8225b6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 04:03:21 +0100 Subject: [PATCH 122/158] MMU: Fix behavior of 64-bit memory reads (used by FPU and MMX), should no longer waste host cycles on extra unnecessary MMU translations and should also no longer MMU translate already translated addresses which was causing unpredictable results. --- src/mem/mem.c | 24 +++++++++++++++++++++--- src/mem/mmu_2386.c | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/mem/mem.c b/src/mem/mem.c index 94c4ab788..074b44bda 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -1533,10 +1533,28 @@ readmemql(uint32_t addr) addr = addr64a[0] & rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32); - return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); + if (map && map->read_l) + return map->read_l(addr, map->priv) | + ((uint64_t) map->read_l(addr + 4, map->priv) << 32); + + if (map && map->read_w) + return map->read_w(addr, map->priv) | + ((uint64_t) map->read_w(addr + 2, map->priv) << 16) | + ((uint64_t) map->read_w(addr + 4, map->priv) << 32) | + ((uint64_t) map->read_w(addr + 6, map->priv) << 48); + + if (map && map->read_b) + return map->read_b(addr, map->priv) | + ((uint64_t) map->read_b(addr + 1, map->priv) << 8) | + ((uint64_t) map->read_b(addr + 2, map->priv) << 16) | + ((uint64_t) map->read_b(addr + 3, map->priv) << 24) | + ((uint64_t) map->read_b(addr + 4, map->priv) << 32) | + ((uint64_t) map->read_b(addr + 5, map->priv) << 40) | + ((uint64_t) map->read_b(addr + 6, map->priv) << 48) | + ((uint64_t) map->read_b(addr + 7, map->priv) << 56); + + return 0xffffffffffffffffULL; } void diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index 7418a88d8..1a2782237 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -102,8 +102,8 @@ mem_readw_map(uint32_t addr) if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) ret = map->read_w(addr, map->priv); else { - ret = mem_readb_phys(addr + 1) << 8; - ret |= mem_readb_phys(addr); + ret = mem_readb_map(addr); + ret |= ((uint16_t) mem_readb_map(addr + 1)) << 8; } return ret; @@ -120,8 +120,8 @@ mem_readl_map(uint32_t addr) if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) ret = map->read_l(addr, map->priv); else { - ret = mem_readw_phys(addr + 2) << 16; - ret |= mem_readw_phys(addr); + ret = mem_readw_map(addr); + ret |= ((uint32_t) mem_readw_map(addr + 2)) << 16; } return ret; @@ -148,8 +148,8 @@ mem_writew_map(uint32_t addr, uint16_t val) if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) map->write_w(addr, val, map->priv); else { - mem_writeb_phys(addr, val & 0xff); - mem_writeb_phys(addr + 1, val >> 8); + mem_writeb_map(addr, val & 0xff); + mem_writeb_map(addr + 1, val >> 8); } } @@ -161,10 +161,10 @@ mem_writel_map(uint32_t addr, uint32_t val) mem_logical_addr = 0xffffffff; if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) - map->write_l(addr, val, map->priv); + map->write_l(addr, val, map->priv); else { - mem_writew_phys(addr, val & 0xffff); - mem_writew_phys(addr + 2, val >> 16); + mem_writew_map(addr, val & 0xffff); + mem_writew_map(addr + 2, val >> 16); } } @@ -649,7 +649,7 @@ readmemll_2386(uint32_t addr) /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass their result as a parameter to be used if needed. */ return readmemwl_no_mmut_2386(addr, addr64a) | - (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); + (((uint32_t) readmemwl_no_mmut_2386(addr + 2, &(addr64a[2]))) << 16); } } @@ -925,10 +925,28 @@ readmemql_2386(uint32_t addr) addr = addr64a[0] & rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32); - return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); + if (map && map->read_l) + return map->read_l(addr, map->priv) | + ((uint64_t) map->read_l(addr + 4, map->priv) << 32); + + if (map && map->read_w) + return map->read_w(addr, map->priv) | + ((uint64_t) map->read_w(addr + 2, map->priv) << 16) | + ((uint64_t) map->read_w(addr + 4, map->priv) << 32) | + ((uint64_t) map->read_w(addr + 6, map->priv) << 48); + + if (map && map->read_b) + return map->read_b(addr, map->priv) | + ((uint64_t) map->read_b(addr + 1, map->priv) << 8) | + ((uint64_t) map->read_b(addr + 2, map->priv) << 16) | + ((uint64_t) map->read_b(addr + 3, map->priv) << 24) | + ((uint64_t) map->read_b(addr + 4, map->priv) << 32) | + ((uint64_t) map->read_b(addr + 5, map->priv) << 40) | + ((uint64_t) map->read_b(addr + 6, map->priv) << 48) | + ((uint64_t) map->read_b(addr + 7, map->priv) << 56); + + return 0xffffffffffffffffULL; } void From 8da843bb0acc529bb3791aa41fcde385f5e21ae6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 06:29:11 +0100 Subject: [PATCH 123/158] DMA: Fix a long-standing nasty bug in bus master transfers that was potentially causing memory corruption. --- src/dma.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dma.c b/src/dma.c index 4edeb39f8..a730f1a1c 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1877,15 +1877,15 @@ dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int Tra n2 = TotalSize - n; /* Do the divisible block, if there is one. */ - if (n) { - for (uint32_t i = 0; i < n; i += TransferSize) + if (n2) { + for (uint32_t i = 0; i < n2; i += TransferSize) mem_read_phys((void *) &(DataRead[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ - if (n2) { - mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); - memcpy((void *) &(DataRead[n]), bytes, n2); + if (n) { + mem_read_phys((void *) bytes, PhysAddress + n2, TransferSize); + memcpy((void *) &(DataRead[n2]), bytes, n); } } @@ -1900,16 +1900,16 @@ dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, n2 = TotalSize - n; /* Do the divisible block, if there is one. */ - if (n) { - for (uint32_t i = 0; i < n; i += TransferSize) + if (n2) { + for (uint32_t i = 0; i < n2; i += TransferSize) mem_write_phys((void *) &(DataWrite[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ - if (n2) { - mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); - memcpy(bytes, (void *) &(DataWrite[n]), n2); - mem_write_phys((void *) bytes, PhysAddress + n, TransferSize); + if (n) { + mem_read_phys((void *) bytes, PhysAddress + n2, TransferSize); + memcpy(bytes, (void *) &(DataWrite[n2]), n); + mem_write_phys((void *) bytes, PhysAddress + n2, TransferSize); } if (dma_at) From d7529d4f5eb2ae4c8cbdbb1280ed2e4942b43da7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 06:32:12 +0100 Subject: [PATCH 124/158] Reverted the fix because it turned out I had actually misread the code. --- src/dma.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dma.c b/src/dma.c index a730f1a1c..4edeb39f8 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1877,15 +1877,15 @@ dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int Tra n2 = TotalSize - n; /* Do the divisible block, if there is one. */ - if (n2) { - for (uint32_t i = 0; i < n2; i += TransferSize) + if (n) { + for (uint32_t i = 0; i < n; i += TransferSize) mem_read_phys((void *) &(DataRead[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ - if (n) { - mem_read_phys((void *) bytes, PhysAddress + n2, TransferSize); - memcpy((void *) &(DataRead[n2]), bytes, n); + if (n2) { + mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); + memcpy((void *) &(DataRead[n]), bytes, n2); } } @@ -1900,16 +1900,16 @@ dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, n2 = TotalSize - n; /* Do the divisible block, if there is one. */ - if (n2) { - for (uint32_t i = 0; i < n2; i += TransferSize) + if (n) { + for (uint32_t i = 0; i < n; i += TransferSize) mem_write_phys((void *) &(DataWrite[i]), PhysAddress + i, TransferSize); } /* Do the non-divisible block, if there is one. */ - if (n) { - mem_read_phys((void *) bytes, PhysAddress + n2, TransferSize); - memcpy(bytes, (void *) &(DataWrite[n2]), n); - mem_write_phys((void *) bytes, PhysAddress + n2, TransferSize); + if (n2) { + mem_read_phys((void *) bytes, PhysAddress + n, TransferSize); + memcpy(bytes, (void *) &(DataWrite[n]), n2); + mem_write_phys((void *) bytes, PhysAddress + n, TransferSize); } if (dma_at) From 556aca0b4edbc24412b3a6ae0cca5243f4673389 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 25 Mar 2025 07:13:50 +0100 Subject: [PATCH 125/158] NEAT/NEATsx: Fix the base of extended memory when EMS is enabled. --- src/chipset/neat.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/chipset/neat.c b/src/chipset/neat.c index ffc25d6d9..1146ecbff 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -688,7 +688,7 @@ remap_update(neat_t *dev, uint8_t val) if (dev->remap_base > 1024) { uint32_t base = (val & RB7_EMSEN) ? (0x00100000 + (dev->ems_size << 10)) : 0x00100000; - mem_mapping_set_addr(&ram_high_mapping, base, (dev->remap_base << 10) - 0x00100000); + mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (dev->remap_base << 10) - 0x00100000); mem_mapping_set_exec(&ram_high_mapping, &(ram[base])); } else mem_mapping_disable(&ram_high_mapping); @@ -942,6 +942,13 @@ neat_write(uint16_t port, uint8_t val, void *priv) break; } + if (mem_size < 1024) + /* No RAM left for EMS at all. */ + dev->ems_size = 0; + else if (mem_size < (dev->ems_size + 1024)) + /* Limit EMS size to the entirety of the remaining extended memory. */ + dev->ems_size = mem_size - 1024; + if (dev->regs[REG_RB7] & RB7_EMSEN) { remap_update(dev, dev->regs[REG_RB7]); From ce820df1d1df691780bd13e745322a127a670865 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 02:08:12 +0600 Subject: [PATCH 126/158] Always make sure emulator is not off-screen when resizing --- src/qt/qt_mainwindow.cpp | 24 ++++++++++++++++++++++++ src/qt/qt_mainwindow.hpp | 1 + src/qt/qt_rendererstack.hpp | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index ccaf6964f..b3d0d9fa9 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -798,6 +798,30 @@ MainWindow::closeEvent(QCloseEvent *event) event->accept(); } +void +MainWindow::resizeEvent(QResizeEvent *event) +{ + //qDebug() << pos().x() + event->size().width(); + //qDebug() << pos().y() + event->size().height(); + if (vid_resize == 1) + return; + + int newX = pos().x(); + int newY = pos().y(); + + if (((frameGeometry().x() + event->size().width() + 1) > util::screenOfWidget(this)->availableGeometry().right())) { + //move(util::screenOfWidget(this)->availableGeometry().right() - size().width() - 1, pos().y()); + newX = util::screenOfWidget(this)->availableGeometry().right() - frameGeometry().width() - 1; + if (newX < 1) newX = 1; + } + + if (((frameGeometry().y() + event->size().height() + 1) > util::screenOfWidget(this)->availableGeometry().bottom())) { + newY = util::screenOfWidget(this)->availableGeometry().bottom() - frameGeometry().height() - 1; + if (newY < 1) newY = 1; + } + move(newX, newY); +} + void MainWindow::initRendererMonitorSlot(int monitor_index) { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 479ed38a4..f1c6cadf6 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -137,6 +137,7 @@ protected: void showEvent(QShowEvent *event) override; void closeEvent(QCloseEvent *event) override; void changeEvent(QEvent *event) override; + void resizeEvent(QResizeEvent *event) override; private slots: void on_actionPen_triggered(); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 54ea49bb9..172dc2fe6 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -14,6 +15,7 @@ #include #include "qt_renderercommon.hpp" +#include "qt_util.hpp" #include @@ -21,6 +23,11 @@ namespace Ui { class RendererStack; } +extern "C" +{ + extern int vid_resize; +} + class RendererCommon; class RendererStack : public QStackedWidget { Q_OBJECT @@ -43,6 +50,22 @@ public: void changeEvent(QEvent *event) override; void resizeEvent(QResizeEvent *event) override { + if (this->m_monitor_index != 0 && vid_resize != 1) { + int newX = pos().x(); + int newY = pos().y(); + + if (((frameGeometry().x() + event->size().width() + 1) > util::screenOfWidget(this)->availableGeometry().right())) { + //move(util::screenOfWidget(this)->availableGeometry().right() - size().width() - 1, pos().y()); + newX = util::screenOfWidget(this)->availableGeometry().right() - frameGeometry().width() - 1; + if (newX < 1) newX = 1; + } + + if (((frameGeometry().y() + event->size().height() + 1) > util::screenOfWidget(this)->availableGeometry().bottom())) { + newY = util::screenOfWidget(this)->availableGeometry().bottom() - frameGeometry().height() - 1; + if (newY < 1) newY = 1; + } + move(newX, newY); + } onResize(event->size().width(), event->size().height()); } void keyPressEvent(QKeyEvent *event) override From 3380783876290bcb148f7e7573dabe428acd6697 Mon Sep 17 00:00:00 2001 From: flama12333 <143599905+flama12333@users.noreply.github.com> Date: Tue, 25 Mar 2025 21:42:01 -0500 Subject: [PATCH 127/158] Replace MACHINE_PCI with MACHINE_PS2_PCI for pl4600c machine_table.c this will be solved the ps2 mouse not appear on the setting --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 9f2d0ce47..62a0e1374 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8902,7 +8902,7 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM, .ram = { .min = 1024, From bd8bade3fbe7d48208d717768abca7536522f9c2 Mon Sep 17 00:00:00 2001 From: flama12333 <143599905+flama12333@users.noreply.github.com> Date: Wed, 26 Mar 2025 01:32:24 -0500 Subject: [PATCH 128/158] update machine_table.c --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 62a0e1374..aa9bae305 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -9358,7 +9358,7 @@ const machine_t machines[] = { .min_multi = MACHINE_MULTIPLIER_FIXED, .max_multi = MACHINE_MULTIPLIER_FIXED }, - .bus_flags = MACHINE_PCI, + .bus_flags = MACHINE_PS2_PCI, .flags = MACHINE_IDE | MACHINE_APM, .ram = { .min = 2048, From e5aed7f9e6e13302203e2ac88fd5ff5234392c88 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 16:37:59 +0600 Subject: [PATCH 129/158] Add confirmation dialog checkboxes in Preferences --- src/qt/qt_progsettings.cpp | 4 + src/qt/qt_progsettings.ui | 194 ++++++++++++++++++++----------------- 2 files changed, 108 insertions(+), 90 deletions(-) diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 6ec76a290..059005ca4 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -116,6 +116,8 @@ ProgSettings::ProgSettings(QWidget *parent) ui->horizontalSlider->setValue(mouseSensitivity * 100.); ui->openDirUsrPath->setChecked(open_dir_usr_path > 0); ui->checkBoxMultimediaKeys->setChecked(inhibit_multimedia_keys); + ui->checkBoxConfirmExit->setChecked(confirm_exit); + ui->checkBoxConfirmSave->setChecked(confirm_save); #ifndef Q_OS_WINDOWS ui->checkBoxMultimediaKeys->setHidden(true); #endif @@ -127,6 +129,8 @@ ProgSettings::accept() strcpy(icon_set, ui->comboBox->currentData().toString().toUtf8().data()); lang_id = ui->comboBoxLanguage->currentData().toUInt(); open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; + confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0; + confirm_save = ui->checkBoxConfirmSave->isChecked() ? 1 : 0; inhibit_multimedia_keys = ui->checkBoxMultimediaKeys->isChecked(); loadTranslators(QCoreApplication::instance()); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index dc5674425..2dbaa739d 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -29,56 +29,25 @@ QLayout::SizeConstraint::SetFixedSize - - - - <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> + + + + Qt::Orientation::Horizontal + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + - Select media images from program working directory + Default - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - 30 - - - - (System Default) - - - - - - + + Default @@ -97,13 +66,20 @@ - - - - Qt::Orientation::Horizontal + + + + Default - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> + + + Select media images from program working directory @@ -121,6 +97,80 @@ + + + + Ask for confirmation before saving settings + + + + + + + 30 + + + + (System Default) + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Inhibit multimedia keys on Windows + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + false + + + 30 + + + + (Default) + + + + + + + + Mouse sensitivity: + + + @@ -143,46 +193,10 @@ - - - - false - - - 30 - - - - (Default) - - - - - - + + - Mouse sensitivity: - - - - - - - Default - - - - - - - Default - - - - - - - Inhibit multimedia keys on Windows + Ask for confirmation before quitting From 38de9b7a1b52a04f300b285bf0a7530d30a67d7d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 16:52:35 +0600 Subject: [PATCH 130/158] Add the other two confirmation dialog checkboxes in Preferences --- src/qt/qt_progsettings.cpp | 5 + src/qt/qt_progsettings.ui | 204 ++++++++++++++++++++----------------- 2 files changed, 114 insertions(+), 95 deletions(-) diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 059005ca4..ce6c21dd6 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -118,6 +118,9 @@ ProgSettings::ProgSettings(QWidget *parent) ui->checkBoxMultimediaKeys->setChecked(inhibit_multimedia_keys); ui->checkBoxConfirmExit->setChecked(confirm_exit); ui->checkBoxConfirmSave->setChecked(confirm_save); + ui->checkBoxConfirmHardReset->setChecked(confirm_reset); + ui->checkBoxFullscreenFirst->setChecked(video_fullscreen_first); + #ifndef Q_OS_WINDOWS ui->checkBoxMultimediaKeys->setHidden(true); #endif @@ -131,6 +134,8 @@ ProgSettings::accept() open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0; confirm_save = ui->checkBoxConfirmSave->isChecked() ? 1 : 0; + confirm_reset = ui->checkBoxConfirmHardReset->isChecked() ? 1 : 0; + video_fullscreen_first = ui->checkBoxFullscreenFirst->isChecked() ? 1 : 0; inhibit_multimedia_keys = ui->checkBoxMultimediaKeys->isChecked(); loadTranslators(QCoreApplication::instance()); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index 2dbaa739d..f7b32ce84 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -7,7 +7,7 @@ 0 0 458 - 374 + 391 @@ -29,43 +29,6 @@ QLayout::SizeConstraint::SetFixedSize - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - - - - - Default - - - - - - - Default - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - @@ -73,16 +36,6 @@ - - - - <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> - - - Select media images from program working directory - - - @@ -90,32 +43,6 @@ - - - - Language: - - - - - - - Ask for confirmation before saving settings - - - - - - - 30 - - - - (System Default) - - - - @@ -129,10 +56,32 @@ - - + + + + 30 + + + + (System Default) + + + + + + + + <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> + - Inhibit multimedia keys on Windows + Select media images from program working directory + + + + + + + Default @@ -149,25 +98,10 @@ - - - - false - - - 30 - - - - (Default) - - - - - - + + - Mouse sensitivity: + Default @@ -193,6 +127,79 @@ + + + + Language: + + + + + + + Ask for confirmation before saving settings + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + Inhibit multimedia keys on Windows + + + + + + + false + + + 30 + + + + (Default) + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Mouse sensitivity: + + + + + + + Ask for confirmation before hard resetting + + + @@ -200,6 +207,13 @@ + + + + Display hotkey message when entering full-screen mode + + + From 0a5fa0da39c12d3f438ea7197943bdf0e2df38e0 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 18 Jan 2025 15:47:41 +0500 Subject: [PATCH 131/158] Add variants of the CH Flightstick Pro and Thrustmaster FCS with rudder pedals (CH Pedals and Thrustmaster RCS respectively) attached --- src/game/gameport.c | 26 +++++++------- src/game/joystick_ch_flightstick_pro.c | 38 ++++++++++++++++++++ src/game/joystick_tm_fcs.c | 48 ++++++++++++++++++++++++++ src/include/86box/gameport.h | 2 ++ 4 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/game/gameport.c b/src/game/gameport.c index 90986a655..8ae1c7d25 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -88,18 +88,20 @@ static const joystick_if_t joystick_none = { static const struct { const joystick_if_t *joystick; } joysticks[] = { - { &joystick_none }, - { &joystick_2axis_2button }, - { &joystick_2axis_4button }, - { &joystick_2axis_6button }, - { &joystick_2axis_8button }, - { &joystick_3axis_2button }, - { &joystick_3axis_4button }, - { &joystick_4axis_4button }, - { &joystick_ch_flightstick_pro }, - { &joystick_sw_pad }, - { &joystick_tm_fcs }, - { NULL } + { &joystick_none }, + { &joystick_2axis_2button }, + { &joystick_2axis_4button }, + { &joystick_2axis_6button }, + { &joystick_2axis_8button }, + { &joystick_3axis_2button }, + { &joystick_3axis_4button }, + { &joystick_4axis_4button }, + { &joystick_ch_flightstick_pro }, + { &joystick_ch_flightstick_pro_ch_pedals }, + { &joystick_sw_pad }, + { &joystick_tm_fcs }, + { &joystick_tm_fcs_rcs }, + { NULL } }; static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL }; diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 6aaaa5dc5..5b240f3f4 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -112,6 +112,26 @@ ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis) } } +static int +ch_flightstick_pro_ch_pedals_read_axis(UNUSED(void *priv), int axis) +{ + if (!JOYSTICK_PRESENT(0, 0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0][0].axis[0]; + case 1: + return joystick_state[0][0].axis[1]; + case 2: + return joystick_state[0][0].axis[3]; + case 3: + return joystick_state[0][0].axis[2]; + default: + return 0; + } +} + static void ch_flightstick_pro_a0_over(UNUSED(void *priv)) { @@ -135,3 +155,21 @@ const joystick_if_t joystick_ch_flightstick_pro = { .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, .pov_names = { "POV" } }; + +const joystick_if_t joystick_ch_flightstick_pro_ch_pedals = { + .name = "CH Flightstick Pro + CH Pedals", + .internal_name = "ch_flightstick_pro_ch_pedals", + .init = ch_flightstick_pro_init, + .close = ch_flightstick_pro_close, + .read = ch_flightstick_pro_read, + .write = ch_flightstick_pro_write, + .read_axis = ch_flightstick_pro_ch_pedals_read_axis, + .a0_over = ch_flightstick_pro_a0_over, + .axis_count = 4, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Throttle", "Rudder" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } +}; diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 4440b039e..52d77d8fb 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -112,6 +112,36 @@ tm_fcs_read_axis(UNUSED(void *priv), int axis) } } +static int +tm_fcs_rcs_read_axis(UNUSED(void *priv), int axis) +{ + if (!JOYSTICK_PRESENT(0, 0)) + return AXIS_NOT_PRESENT; + + switch (axis) { + case 0: + return joystick_state[0][0].axis[0]; + case 1: + return joystick_state[0][0].axis[1]; + case 2: + return joystick_state[0][0].axis[2]; + case 3: + if (joystick_state[0][0].pov[0] == -1) + return 32767; + if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45) + return -32768; + if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135) + return -16384; + if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225) + return 0; + if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315) + return 16384; + return 0; + default: + return 0; + } +} + static void tm_fcs_a0_over(UNUSED(void *priv)) { @@ -135,3 +165,21 @@ const joystick_if_t joystick_tm_fcs = { .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, .pov_names = { "POV" } }; + +const joystick_if_t joystick_tm_fcs_rcs = { + .name = "Thrustmaster FCS + Rudder Control System", + .internal_name = "thrustmaster_fcs_rcs", + .init = tm_fcs_init, + .close = tm_fcs_close, + .read = tm_fcs_read, + .write = tm_fcs_write, + .read_axis = tm_fcs_rcs_read_axis, + .a0_over = tm_fcs_a0_over, + .axis_count = 3, + .button_count = 4, + .pov_count = 1, + .max_joysticks = 1, + .axis_names = { "X axis", "Y axis", "Rudder" }, + .button_names = { "Button 1", "Button 2", "Button 3", "Button 4" }, + .pov_names = { "POV" } +}; diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index c5fc1d192..7928cdd30 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -179,10 +179,12 @@ extern const joystick_if_t joystick_2axis_6button; extern const joystick_if_t joystick_2axis_8button; extern const joystick_if_t joystick_ch_flightstick_pro; +extern const joystick_if_t joystick_ch_flightstick_pro_ch_pedals; extern const joystick_if_t joystick_sw_pad; extern const joystick_if_t joystick_tm_fcs; +extern const joystick_if_t joystick_tm_fcs_rcs; extern int gameport_available(int); extern int gameport_has_config(int); From 99e8d13afa047e3dc7d8aa7afae188e4748055a8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 30 Mar 2024 16:21:41 +0600 Subject: [PATCH 132/158] Implement NEC V20/V30's i8080 emulation mode --- src/cpu/8080.c | 290 ------------- src/cpu/808x.c | 168 +++++++- src/cpu/CMakeLists.txt | 2 +- src/cpu/i8080.c | 826 ++++++++++++++++++++++++++++++++++++++ src/cpu/i8080.h | 35 ++ src/include/86box/i8080.h | 69 ---- 6 files changed, 1025 insertions(+), 365 deletions(-) delete mode 100644 src/cpu/8080.c create mode 100644 src/cpu/i8080.c create mode 100644 src/cpu/i8080.h delete mode 100644 src/include/86box/i8080.h diff --git a/src/cpu/8080.c b/src/cpu/8080.c deleted file mode 100644 index 7a7e7b96c..000000000 --- a/src/cpu/8080.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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. - * - * 8080 CPU emulation. - * - * Authors: Cacodemon345 - * - * Copyright 2022 Cacodemon345 - */ - -#include -#include -#include "cpu.h" -#include <86box/timer.h> -#include <86box/i8080.h> -#include <86box/mem.h> -#include <86box/plat_unused.h> - -static int completed = 1; -static int in_rep = 0; -static int repeating = 0; -static int rep_c_flag = 0; -static int oldc; -static int cycdiff; -#ifdef UNUSED_8080_VARS -static int prefetching = 1; -static int refresh = 0; -static int clear_lock = 0; - -static uint32_t cpu_src = 0; -static uint32_t cpu_dest = 0; -static uint32_t cpu_data = 0; -#endif - -static void -clock_start(void) -{ - cycdiff = cycles; -} - -static void -clock_end(void) -{ - int diff = cycdiff - cycles; - - /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += (uint64_t) diff * (xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process(); -} - -static void -i8080_wait(int c, int bus) -{ - cycles -= c; - if (bus < 2) { - clock_end(); - clock_start(); - } -} - -#ifdef UNUSED_8080_FUNCS -static uint8_t -readmemb(uint32_t a) -{ - uint8_t ret; - - i8080_wait(4, 1); - ret = read_mem_b(a); - - return ret; -} - -static uint8_t -ins_fetch(i8080 *cpu) -{ - uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc); - - cpu->pc++; - return ret; -} -#endif - -void -transfer_from_808x(i8080 *cpu) -{ - cpu->hl = BX; - cpu->bc = CX; - cpu->de = DX; - cpu->a = AL; - cpu->flags = cpu_state.flags & 0xFF; - cpu->sp = BP; - cpu->pc = cpu_state.pc; - cpu->oldpc = cpu_state.oldpc; - cpu->pmembase = cs; - cpu->dmembase = ds; -} - -void -transfer_to_808x(i8080 *cpu) -{ - BX = cpu->hl; - CX = cpu->bc; - DX = cpu->de; - AL = cpu->a; - cpu_state.flags &= 0xFF00; - cpu_state.flags |= cpu->flags & 0xFF; - BP = cpu->sp; - cpu_state.pc = cpu->pc; -} - -uint8_t -getreg_i8080(i8080 *cpu, uint8_t reg) -{ - uint8_t ret = 0xFF; - switch (reg) { - case 0x0: - ret = cpu->b; - break; - case 0x1: - ret = cpu->c; - break; - case 0x2: - ret = cpu->d; - break; - case 0x3: - ret = cpu->e; - break; - case 0x4: - ret = cpu->h; - break; - case 0x5: - ret = cpu->l; - break; - case 0x6: - ret = cpu->readmembyte(cpu->dmembase + cpu->sp); - break; - case 0x7: - ret = cpu->a; - break; - } - return ret; -} - -uint8_t -getreg_i8080_emu(i8080 *cpu, uint8_t reg) -{ - uint8_t ret = 0xFF; - switch (reg) { - case 0x0: - ret = CH; - break; - case 0x1: - ret = CL; - break; - case 0x2: - ret = DH; - break; - case 0x3: - ret = DL; - break; - case 0x4: - ret = BH; - break; - case 0x5: - ret = BL; - break; - case 0x6: - ret = cpu->readmembyte(cpu->dmembase + BP); - break; - case 0x7: - ret = AL; - break; - } - return ret; -} - -void -setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val) -{ - switch (reg) { - case 0x0: - CH = val; - break; - case 0x1: - CL = val; - break; - case 0x2: - DH = val; - break; - case 0x3: - DL = val; - break; - case 0x4: - BH = val; - break; - case 0x5: - BL = val; - break; - case 0x6: - cpu->writemembyte(cpu->dmembase + BP, val); - break; - case 0x7: - AL = val; - break; - } -} - -void -setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val) -{ - switch (reg) { - case 0x0: - cpu->b = val; - break; - case 0x1: - cpu->c = val; - break; - case 0x2: - cpu->d = val; - break; - case 0x3: - cpu->e = val; - break; - case 0x4: - cpu->h = val; - break; - case 0x5: - cpu->l = val; - break; - case 0x6: - cpu->writemembyte(cpu->dmembase + cpu->sp, val); - break; - case 0x7: - cpu->a = val; - break; - } -} - -void -interpret_exec8080(UNUSED(i8080 *cpu), uint8_t opcode) -{ - switch (opcode) { - case 0x00: - { - break; - } - } -} - -/* Actually implement i8080 emulation. */ -void -exec8080(i8080 *cpu, int cycs) -{ -#ifdef UNUSED_8080_VARS - uint8_t temp = 0, temp2; - uint8_t old_af; - uint8_t handled = 0; - uint16_t addr, tempw; - uint16_t new_ip; - int bits; -#endif - - cycles += cycs; - - while (cycles > 0) { - cpu->startclock(); - - if (!repeating) { - cpu->oldpc = cpu->pc; - opcode = cpu->fetchinstruction(cpu); - oldc = cpu->flags & C_FLAG_I8080; - i8080_wait(1, 0); - } - completed = 1; - if (completed) { - repeating = 0; - in_rep = 0; - rep_c_flag = 0; - cpu->endclock(); - if (cpu->checkinterrupts) - cpu->checkinterrupts(); - } - } -} diff --git a/src/cpu/808x.c b/src/cpu/808x.c index e3a326503..4ce1fa3b9 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -18,10 +18,13 @@ #include #include #include +#include #include #include #include +#include "i8080.h" + #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" @@ -70,6 +73,9 @@ static int in_rep = 0, repeating = 0, rep_c_flag = 0; static int oldc, clear_lock = 0; static int refresh = 0, cycdiff; +static i8080 emulated_processor; +static bool cpu_md_write_disable = 1; + /* Various things needed for 8087. */ #define OP_TABLE(name) ops_##name @@ -195,6 +201,54 @@ prefetch_queue_get_size(void) { return pfq_size; } +static void set_if(int cond); + +void +sync_from_i8080(void) +{ + AL = emulated_processor.a; + BH = emulated_processor.h; + BL = emulated_processor.l; + CH = emulated_processor.b; + CL = emulated_processor.c; + DH = emulated_processor.d; + DL = emulated_processor.e; + BP = emulated_processor.sp; + + cpu_state.pc = emulated_processor.pc; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= emulated_processor.sf << 7; + cpu_state.flags |= emulated_processor.zf << 6; + cpu_state.flags |= emulated_processor.hf << 4; + cpu_state.flags |= emulated_processor.pf << 2; + cpu_state.flags |= 1 << 1; + cpu_state.flags |= emulated_processor.cf << 0; + set_if(emulated_processor.iff); +} + +void +sync_to_i8080(void) +{ + emulated_processor.a = AL; + emulated_processor.h = BH; + emulated_processor.l = BL; + emulated_processor.b = CH; + emulated_processor.c = CL; + emulated_processor.d = DH; + emulated_processor.e = DL; + emulated_processor.sp = BP; + emulated_processor.pc = cpu_state.pc; + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); + + emulated_processor.sf = (cpu_state.flags >> 7) & 1; + emulated_processor.zf = (cpu_state.flags >> 6) & 1; + emulated_processor.hf = (cpu_state.flags >> 4) & 1; + emulated_processor.pf = (cpu_state.flags >> 2) & 1; + emulated_processor.cf = (cpu_state.flags >> 0) & 1; + + emulated_processor.interrupt_delay = noint; +} + uint16_t get_last_addr(void) @@ -582,6 +636,33 @@ load_seg(uint16_t seg, x86seg *s) s->seg = seg & 0xffff; } +uint8_t fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(cs + addr); +} + +uint8_t fetch_i8080_data(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(ds + addr); +} + +void put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val) +{ + writememb(ds, addr, val); +} + +static uint8_t i8080_port_in(UNUSED(void* priv), uint8_t port) +{ + cpu_io(8, 0, port); + return AL; +} + +static void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) +{ + AL = val; + cpu_io(8, 1, port); +} + void reset_808x(int hard) { @@ -619,6 +700,14 @@ reset_808x(int hard) use_custom_nmi_vector = 0x00; custom_nmi_vector = 0x00000000; + + cpu_md_write_disable = 1; + i8080_init(&emulated_processor); + emulated_processor.write_byte = put_i8080_data; + emulated_processor.read_byte = fetch_i8080_data; + emulated_processor.read_byte_seg = fetch_i8080_opcode; + emulated_processor.port_in = i8080_port_in; + emulated_processor.port_out = i8080_port_out; } static void @@ -994,6 +1083,11 @@ interrupt(uint16_t addr) uint16_t new_cs, new_ip; uint16_t tempf; + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + pclog("CALLN/INT#/NMI#\n"); + } + addr <<= 2; cpu_state.eaaddr = addr; old_cs = CS; @@ -1010,6 +1104,8 @@ interrupt(uint16_t addr) tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; @@ -1020,6 +1116,56 @@ interrupt(uint16_t addr) push(&old_ip); } +/* Ditto, but for breaking into emulation mode. */ +static void +interrupt_brkem(uint16_t addr) +{ + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; + + addr <<= 2; + cpu_state.eaaddr = addr; + old_cs = CS; + access(5, 16); + new_ip = readmemw(0, cpu_state.eaaddr); + wait(1, 0); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); + new_cs = readmemw(0, cpu_state.eaaddr); + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + push(&tempf); + cpu_state.flags &= ~(MD_FLAG); + cpu_md_write_disable = 0; + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); + sync_to_i8080(); + pclog("BRKEM mode\n"); +} + +void +retem_i8080(void) +{ + sync_from_i8080(); + + cpu_state.pc = pop(); + CS = pop(); + cpu_state.flags = pop() | MD_FLAG; + + cpu_md_write_disable = 1; + pclog("RETEM mode\n"); +} + void interrupt_808x(uint16_t addr) { @@ -1771,6 +1917,15 @@ execx86(int cycs) while (cycles > 0) { clock_start(); + if (is_nec && !(cpu_state.flags & MD_FLAG)) { + i8080_step(&emulated_processor); + set_if(emulated_processor.iff); + cycles -= emulated_processor.cyc; + emulated_processor.cyc = 0; + completed = 1; + goto exec_completed; + } + if (!repeating) { cpu_state.oldpc = cpu_state.pc; opcode = pfq_fetchb(); @@ -2344,8 +2499,8 @@ execx86(int cycs) break; case 0xFF: /* BRKEM */ - /* Unimplemented for now. */ - fatal("808x: Unsupported 8080 emulation mode attempted to enter into!"); + interrupt_brkem(pfq_fetchb()); + handled = 1; break; default: @@ -2857,11 +3012,12 @@ execx86(int cycs) break; case 0x9D: /*POPF*/ access(25, 16); - if (is_nec) + if (is_nec && cpu_md_write_disable) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; wait(1, 0); + sync_to_i8080(); break; case 0x9E: /*SAHF*/ wait(1, 0); @@ -3127,13 +3283,15 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - if (is_nec) + if (is_nec && cpu_md_write_disable) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; wait(5, 0); noint = 1; nmi_enable = 1; + if (is_nec && !(cpu_state.flags & MD_FLAG)) + sync_to_i8080(); break; case 0xD0: @@ -3659,7 +3817,7 @@ execx86(int cycs) break; } } - +exec_completed: if (completed) { repeating = 0; ovr_seg = NULL; diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 9c1385d4f..dc7f5ac11 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -29,7 +29,7 @@ add_library(cpu OBJECT x86seg_2386.c x87.c x87_timings.c - 8080.c + i8080.c ) if(AMD_K5) diff --git a/src/cpu/i8080.c b/src/cpu/i8080.c new file mode 100644 index 000000000..688923997 --- /dev/null +++ b/src/cpu/i8080.c @@ -0,0 +1,826 @@ +/* + * 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. + * + * Intel 8080 CPU emulation + * + * Authors: Cacodemon345 + * Nicolas Allemand + * + * Copyright (c) 2018 Nicolas Allemand + * Copyright (c) 2024 Cacodemon345 + * + */ + +#include "i8080.h" +#include + +// Changes from upstream: +// Add CALLN and RETEM instructions. +// Add code for instruction fetches. + +// this array defines the number of cycles one opcode takes. +// note that there are some special cases: conditional RETs and CALLs +// add +6 cycles if the condition is met +// clang-format off +static const uint8_t OPCODES_CYCLES[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 0 + 4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 1 + 4, 10, 16, 5, 5, 5, 7, 4, 4, 10, 16, 5, 5, 5, 7, 4, // 2 + 4, 10, 13, 5, 10, 10, 10, 4, 4, 10, 13, 5, 5, 5, 7, 4, // 3 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 4 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 5 + 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 6 + 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5, // 7 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9 + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A + 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B + 5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // C + 5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // D + 5, 10, 10, 18, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11, // E + 5, 10, 10, 4, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11 // F +}; +// clang-format on + +static const char* DISASSEMBLE_TABLE[] = {"nop", "lxi b,#", "stax b", "inx b", + "inr b", "dcr b", "mvi b,#", "rlc", "ill", "dad b", "ldax b", "dcx b", + "inr c", "dcr c", "mvi c,#", "rrc", "ill", "lxi d,#", "stax d", "inx d", + "inr d", "dcr d", "mvi d,#", "ral", "ill", "dad d", "ldax d", "dcx d", + "inr e", "dcr e", "mvi e,#", "rar", "ill", "lxi h,#", "shld", "inx h", + "inr h", "dcr h", "mvi h,#", "daa", "ill", "dad h", "lhld", "dcx h", + "inr l", "dcr l", "mvi l,#", "cma", "ill", "lxi sp,#", "sta $", "inx sp", + "inr M", "dcr M", "mvi M,#", "stc", "ill", "dad sp", "lda $", "dcx sp", + "inr a", "dcr a", "mvi a,#", "cmc", "mov b,b", "mov b,c", "mov b,d", + "mov b,e", "mov b,h", "mov b,l", "mov b,M", "mov b,a", "mov c,b", "mov c,c", + "mov c,d", "mov c,e", "mov c,h", "mov c,l", "mov c,M", "mov c,a", "mov d,b", + "mov d,c", "mov d,d", "mov d,e", "mov d,h", "mov d,l", "mov d,M", "mov d,a", + "mov e,b", "mov e,c", "mov e,d", "mov e,e", "mov e,h", "mov e,l", "mov e,M", + "mov e,a", "mov h,b", "mov h,c", "mov h,d", "mov h,e", "mov h,h", "mov h,l", + "mov h,M", "mov h,a", "mov l,b", "mov l,c", "mov l,d", "mov l,e", "mov l,h", + "mov l,l", "mov l,M", "mov l,a", "mov M,b", "mov M,c", "mov M,d", "mov M,e", + "mov M,h", "mov M,l", "hlt", "mov M,a", "mov a,b", "mov a,c", "mov a,d", + "mov a,e", "mov a,h", "mov a,l", "mov a,M", "mov a,a", "add b", "add c", + "add d", "add e", "add h", "add l", "add M", "add a", "adc b", "adc c", + "adc d", "adc e", "adc h", "adc l", "adc M", "adc a", "sub b", "sub c", + "sub d", "sub e", "sub h", "sub l", "sub M", "sub a", "sbb b", "sbb c", + "sbb d", "sbb e", "sbb h", "sbb l", "sbb M", "sbb a", "ana b", "ana c", + "ana d", "ana e", "ana h", "ana l", "ana M", "ana a", "xra b", "xra c", + "xra d", "xra e", "xra h", "xra l", "xra M", "xra a", "ora b", "ora c", + "ora d", "ora e", "ora h", "ora l", "ora M", "ora a", "cmp b", "cmp c", + "cmp d", "cmp e", "cmp h", "cmp l", "cmp M", "cmp a", "rnz", "pop b", + "jnz $", "jmp $", "cnz $", "push b", "adi #", "rst 0", "rz", "ret", "jz $", + "ill", "cz $", "call $", "aci #", "rst 1", "rnc", "pop d", "jnc $", "out p", + "cnc $", "push d", "sui #", "rst 2", "rc", "ill", "jc $", "in p", "cc $", + "ill", "sbi #", "rst 3", "rpo", "pop h", "jpo $", "xthl", "cpo $", "push h", + "ani #", "rst 4", "rpe", "pchl", "jpe $", "xchg", "cpe $", "ill", "xri #", + "rst 5", "rp", "pop psw", "jp $", "di", "cp $", "push psw", "ori #", + "rst 6", "rm", "sphl", "jm $", "ei", "cm $", "ill", "cpi #", "rst 7"}; + +#define SET_ZSP(c, val) \ + do { \ + c->zf = (val) == 0; \ + c->sf = (val) >> 7; \ + c->pf = parity(val); \ + } while (0) + +// memory helpers (the only four to use `read_byte` and `write_byte` function +// pointers) + +// reads a byte from memory +static inline uint8_t i8080_rb(i8080* const c, uint16_t addr) { + return c->read_byte(c->userdata, addr); +} + +// writes a byte to memory +static inline void i8080_wb(i8080* const c, uint16_t addr, uint8_t val) { + c->write_byte(c->userdata, addr, val); +} + +// reads a word from memory +static inline uint16_t i8080_rw(i8080* const c, uint16_t addr) { + return c->read_byte(c->userdata, addr + 1) << 8 | + c->read_byte(c->userdata, addr); +} + +// writes a word to memory +static inline void i8080_ww(i8080* const c, uint16_t addr, uint16_t val) { + c->write_byte(c->userdata, addr, val & 0xFF); + c->write_byte(c->userdata, addr + 1, val >> 8); +} + +// returns the next byte in memory (and updates the program counter) +static inline uint8_t i8080_next_byte(i8080* const c) { + return c->read_byte_seg ? (c->read_byte_seg(c->userdata, c->pc++)) : i8080_rb(c, c->pc++); +} + +// returns the next word in memory (and updates the program counter) +static inline uint16_t i8080_next_word(i8080* const c) { + uint16_t result = 0; + if (c->read_byte_seg) + result = c->read_byte_seg(c, c->pc) | (c->read_byte_seg(c, c->pc + 1) << 8); + else + result = i8080_rw(c, c->pc); + c->pc += 2; + return result; +} + +// paired registers helpers (setters and getters) +static inline void i8080_set_bc(i8080* const c, uint16_t val) { + c->b = val >> 8; + c->c = val & 0xFF; +} + +static inline void i8080_set_de(i8080* const c, uint16_t val) { + c->d = val >> 8; + c->e = val & 0xFF; +} + +static inline void i8080_set_hl(i8080* const c, uint16_t val) { + c->h = val >> 8; + c->l = val & 0xFF; +} + +static inline uint16_t i8080_get_bc(i8080* const c) { + return (c->b << 8) | c->c; +} + +static inline uint16_t i8080_get_de(i8080* const c) { + return (c->d << 8) | c->e; +} + +static inline uint16_t i8080_get_hl(i8080* const c) { + return (c->h << 8) | c->l; +} + +// stack helpers + +// pushes a value into the stack and updates the stack pointer +static inline void i8080_push_stack(i8080* const c, uint16_t val) { + c->sp -= 2; + i8080_ww(c, c->sp, val); +} + +// pops a value from the stack and updates the stack pointer +static inline uint16_t i8080_pop_stack(i8080* const c) { + uint16_t val = i8080_rw(c, c->sp); + c->sp += 2; + return val; +} + +// opcodes + +// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1 +static inline bool parity(uint8_t val) { + uint8_t nb_one_bits = 0; + for (int i = 0; i < 8; i++) { + nb_one_bits += ((val >> i) & 1); + } + + return (nb_one_bits & 1) == 0; +} + +// returns if there was a carry between bit "bit_no" and "bit_no - 1" when +// executing "a + b + cy" +static inline bool carry(int bit_no, uint8_t a, uint8_t b, bool cy) { + int16_t result = a + b + cy; + int16_t carry = result ^ a ^ b; + return carry & (1 << bit_no); +} + +// adds a value (+ an optional carry flag) to a register +static inline void i8080_add( + i8080* const c, uint8_t* const reg, uint8_t val, bool cy) { + uint8_t result = *reg + val + cy; + c->cf = carry(8, *reg, val, cy); + c->hf = carry(4, *reg, val, cy); + SET_ZSP(c, result); + *reg = result; +} + +// substracts a byte (+ an optional carry flag) from a register +// see https://stackoverflow.com/a/8037485 +static inline void i8080_sub( + i8080* const c, uint8_t* const reg, uint8_t val, bool cy) { + i8080_add(c, reg, ~val, !cy); + c->cf = !c->cf; +} + +// adds a word to HL +static inline void i8080_dad(i8080* const c, uint16_t val) { + c->cf = ((i8080_get_hl(c) + val) >> 16) & 1; + i8080_set_hl(c, i8080_get_hl(c) + val); +} + +// increments a byte +static inline uint8_t i8080_inr(i8080* const c, uint8_t val) { + uint8_t result = val + 1; + c->hf = (result & 0xF) == 0; + SET_ZSP(c, result); + return result; +} + +// decrements a byte +static inline uint8_t i8080_dcr(i8080* const c, uint8_t val) { + uint8_t result = val - 1; + c->hf = !((result & 0xF) == 0xF); + SET_ZSP(c, result); + return result; +} + +// executes a logic "and" between register A and a byte, then stores the +// result in register A +static inline void i8080_ana(i8080* const c, uint8_t val) { + uint8_t result = c->a & val; + c->cf = 0; + c->hf = ((c->a | val) & 0x08) != 0; + SET_ZSP(c, result); + c->a = result; +} + +// executes a logic "xor" between register A and a byte, then stores the +// result in register A +static inline void i8080_xra(i8080* const c, uint8_t val) { + c->a ^= val; + c->cf = 0; + c->hf = 0; + SET_ZSP(c, c->a); +} + +// executes a logic "or" between register A and a byte, then stores the +// result in register A +static inline void i8080_ora(i8080* const c, uint8_t val) { + c->a |= val; + c->cf = 0; + c->hf = 0; + SET_ZSP(c, c->a); +} + +// compares the register A to another byte +static inline void i8080_cmp(i8080* const c, uint8_t val) { + int16_t result = c->a - val; + c->cf = result >> 8; + c->hf = ~(c->a ^ result ^ val) & 0x10; + SET_ZSP(c, result & 0xFF); +} + +// sets the program counter to a given address +static inline void i8080_jmp(i8080* const c, uint16_t addr) { + c->pc = addr; +} + +// jumps to next address pointed by the next word in memory if a condition +// is met +static inline void i8080_cond_jmp(i8080* const c, bool condition) { + uint16_t addr = i8080_next_word(c); + if (condition) { + c->pc = addr; + } +} + +// pushes the current pc to the stack, then jumps to an address +static inline void i8080_call(i8080* const c, uint16_t addr) { + i8080_push_stack(c, c->pc); + i8080_jmp(c, addr); +} + +// calls to next word in memory if a condition is met +static inline void i8080_cond_call(i8080* const c, bool condition) { + uint16_t addr = i8080_next_word(c); + if (condition) { + i8080_call(c, addr); + c->cyc += 6; + } +} + +// returns from subroutine +static inline void i8080_ret(i8080* const c) { + c->pc = i8080_pop_stack(c); +} + +// returns from subroutine if a condition is met +static inline void i8080_cond_ret(i8080* const c, bool condition) { + if (condition) { + i8080_ret(c); + c->cyc += 6; + } +} + +// pushes register A and the flags into the stack +static inline void i8080_push_psw(i8080* const c) { + // note: bit 3 and 5 are always 0 + uint8_t psw = 0; + psw |= c->sf << 7; + psw |= c->zf << 6; + psw |= c->hf << 4; + psw |= c->pf << 2; + psw |= 1 << 1; // bit 1 is always 1 + psw |= c->cf << 0; + i8080_push_stack(c, c->a << 8 | psw); +} + +// pops register A and the flags from the stack +static inline void i8080_pop_psw(i8080* const c) { + uint16_t af = i8080_pop_stack(c); + c->a = af >> 8; + uint8_t psw = af & 0xFF; + + c->sf = (psw >> 7) & 1; + c->zf = (psw >> 6) & 1; + c->hf = (psw >> 4) & 1; + c->pf = (psw >> 2) & 1; + c->cf = (psw >> 0) & 1; +} + +// rotate register A left +static inline void i8080_rlc(i8080* const c) { + c->cf = c->a >> 7; + c->a = (c->a << 1) | c->cf; +} + +// rotate register A right +static inline void i8080_rrc(i8080* const c) { + c->cf = c->a & 1; + c->a = (c->a >> 1) | (c->cf << 7); +} + +// rotate register A left with the carry flag +static inline void i8080_ral(i8080* const c) { + bool cy = c->cf; + c->cf = c->a >> 7; + c->a = (c->a << 1) | cy; +} + +// rotate register A right with the carry flag +static inline void i8080_rar(i8080* const c) { + bool cy = c->cf; + c->cf = c->a & 1; + c->a = (c->a >> 1) | (cy << 7); +} + +// Decimal Adjust Accumulator: the eight-bit number in register A is adjusted +// to form two four-bit binary-coded-decimal digits. +// For example, if A=$2B and DAA is executed, A becomes $31. +static inline void i8080_daa(i8080* const c) { + bool cy = c->cf; + uint8_t correction = 0; + + uint8_t lsb = c->a & 0x0F; + uint8_t msb = c->a >> 4; + + if (c->hf || lsb > 9) { + correction += 0x06; + } + + if (c->cf || msb > 9 || (msb >= 9 && lsb > 9)) { + correction += 0x60; + cy = 1; + } + + i8080_add(c, &c->a, correction, 0); + c->cf = cy; +} + +// switches the value of registers DE and HL +static inline void i8080_xchg(i8080* const c) { + uint16_t de = i8080_get_de(c); + i8080_set_de(c, i8080_get_hl(c)); + i8080_set_hl(c, de); +} + +// switches the value of a word at (sp) and HL +static inline void i8080_xthl(i8080* const c) { + uint16_t val = i8080_rw(c, c->sp); + i8080_ww(c, c->sp, i8080_get_hl(c)); + i8080_set_hl(c, val); +} + +extern void interrupt_808x(uint16_t addr); +extern void retem_i8080(void); +// executes one opcode +static inline void i8080_execute(i8080* const c, uint8_t opcode) { + c->cyc += OPCODES_CYCLES[opcode]; + + // when DI is executed, interrupts won't be serviced + // until the end of next instruction: + if (c->interrupt_delay > 0) { + c->interrupt_delay -= 1; + } + + switch (opcode) { + case 0x7F: c->a = c->a; break; // MOV A,A + case 0x78: c->a = c->b; break; // MOV A,B + case 0x79: c->a = c->c; break; // MOV A,C + case 0x7A: c->a = c->d; break; // MOV A,D + case 0x7B: c->a = c->e; break; // MOV A,E + case 0x7C: c->a = c->h; break; // MOV A,H + case 0x7D: c->a = c->l; break; // MOV A,L + case 0x7E: c->a = i8080_rb(c, i8080_get_hl(c)); break; // MOV A,M + + case 0x0A: c->a = i8080_rb(c, i8080_get_bc(c)); break; // LDAX B + case 0x1A: c->a = i8080_rb(c, i8080_get_de(c)); break; // LDAX D + case 0x3A: c->a = i8080_rb(c, i8080_next_word(c)); break; // LDA word + + case 0x47: c->b = c->a; break; // MOV B,A + case 0x40: c->b = c->b; break; // MOV B,B + case 0x41: c->b = c->c; break; // MOV B,C + case 0x42: c->b = c->d; break; // MOV B,D + case 0x43: c->b = c->e; break; // MOV B,E + case 0x44: c->b = c->h; break; // MOV B,H + case 0x45: c->b = c->l; break; // MOV B,L + case 0x46: c->b = i8080_rb(c, i8080_get_hl(c)); break; // MOV B,M + + case 0x4F: c->c = c->a; break; // MOV C,A + case 0x48: c->c = c->b; break; // MOV C,B + case 0x49: c->c = c->c; break; // MOV C,C + case 0x4A: c->c = c->d; break; // MOV C,D + case 0x4B: c->c = c->e; break; // MOV C,E + case 0x4C: c->c = c->h; break; // MOV C,H + case 0x4D: c->c = c->l; break; // MOV C,L + case 0x4E: c->c = i8080_rb(c, i8080_get_hl(c)); break; // MOV C,M + + case 0x57: c->d = c->a; break; // MOV D,A + case 0x50: c->d = c->b; break; // MOV D,B + case 0x51: c->d = c->c; break; // MOV D,C + case 0x52: c->d = c->d; break; // MOV D,D + case 0x53: c->d = c->e; break; // MOV D,E + case 0x54: c->d = c->h; break; // MOV D,H + case 0x55: c->d = c->l; break; // MOV D,L + case 0x56: c->d = i8080_rb(c, i8080_get_hl(c)); break; // MOV D,M + + case 0x5F: c->e = c->a; break; // MOV E,A + case 0x58: c->e = c->b; break; // MOV E,B + case 0x59: c->e = c->c; break; // MOV E,C + case 0x5A: c->e = c->d; break; // MOV E,D + case 0x5B: c->e = c->e; break; // MOV E,E + case 0x5C: c->e = c->h; break; // MOV E,H + case 0x5D: c->e = c->l; break; // MOV E,L + case 0x5E: c->e = i8080_rb(c, i8080_get_hl(c)); break; // MOV E,M + + case 0x67: c->h = c->a; break; // MOV H,A + case 0x60: c->h = c->b; break; // MOV H,B + case 0x61: c->h = c->c; break; // MOV H,C + case 0x62: c->h = c->d; break; // MOV H,D + case 0x63: c->h = c->e; break; // MOV H,E + case 0x64: c->h = c->h; break; // MOV H,H + case 0x65: c->h = c->l; break; // MOV H,L + case 0x66: c->h = i8080_rb(c, i8080_get_hl(c)); break; // MOV H,M + + case 0x6F: c->l = c->a; break; // MOV L,A + case 0x68: c->l = c->b; break; // MOV L,B + case 0x69: c->l = c->c; break; // MOV L,C + case 0x6A: c->l = c->d; break; // MOV L,D + case 0x6B: c->l = c->e; break; // MOV L,E + case 0x6C: c->l = c->h; break; // MOV L,H + case 0x6D: c->l = c->l; break; // MOV L,L + case 0x6E: c->l = i8080_rb(c, i8080_get_hl(c)); break; // MOV L,M + + case 0x77: i8080_wb(c, i8080_get_hl(c), c->a); break; // MOV M,A + case 0x70: i8080_wb(c, i8080_get_hl(c), c->b); break; // MOV M,B + case 0x71: i8080_wb(c, i8080_get_hl(c), c->c); break; // MOV M,C + case 0x72: i8080_wb(c, i8080_get_hl(c), c->d); break; // MOV M,D + case 0x73: i8080_wb(c, i8080_get_hl(c), c->e); break; // MOV M,E + case 0x74: i8080_wb(c, i8080_get_hl(c), c->h); break; // MOV M,H + case 0x75: i8080_wb(c, i8080_get_hl(c), c->l); break; // MOV M,L + + case 0x3E: c->a = i8080_next_byte(c); break; // MVI A,byte + case 0x06: c->b = i8080_next_byte(c); break; // MVI B,byte + case 0x0E: c->c = i8080_next_byte(c); break; // MVI C,byte + case 0x16: c->d = i8080_next_byte(c); break; // MVI D,byte + case 0x1E: c->e = i8080_next_byte(c); break; // MVI E,byte + case 0x26: c->h = i8080_next_byte(c); break; // MVI H,byte + case 0x2E: c->l = i8080_next_byte(c); break; // MVI L,byte + case 0x36: + i8080_wb(c, i8080_get_hl(c), i8080_next_byte(c)); + break; // MVI M,byte + + case 0x02: i8080_wb(c, i8080_get_bc(c), c->a); break; // STAX B + case 0x12: i8080_wb(c, i8080_get_de(c), c->a); break; // STAX D + case 0x32: i8080_wb(c, i8080_next_word(c), c->a); break; // STA word + + case 0x01: i8080_set_bc(c, i8080_next_word(c)); break; // LXI B,word + case 0x11: i8080_set_de(c, i8080_next_word(c)); break; // LXI D,word + case 0x21: i8080_set_hl(c, i8080_next_word(c)); break; // LXI H,word + case 0x31: c->sp = i8080_next_word(c); break; // LXI SP,word + case 0x2A: i8080_set_hl(c, i8080_rw(c, i8080_next_word(c))); break; // LHLD + case 0x22: i8080_ww(c, i8080_next_word(c), i8080_get_hl(c)); break; // SHLD + case 0xF9: c->sp = i8080_get_hl(c); break; // SPHL + + case 0xEB: i8080_xchg(c); break; // XCHG + case 0xE3: i8080_xthl(c); break; // XTHL + + case 0x87: i8080_add(c, &c->a, c->a, 0); break; // ADD A + case 0x80: i8080_add(c, &c->a, c->b, 0); break; // ADD B + case 0x81: i8080_add(c, &c->a, c->c, 0); break; // ADD C + case 0x82: i8080_add(c, &c->a, c->d, 0); break; // ADD D + case 0x83: i8080_add(c, &c->a, c->e, 0); break; // ADD E + case 0x84: i8080_add(c, &c->a, c->h, 0); break; // ADD H + case 0x85: i8080_add(c, &c->a, c->l, 0); break; // ADD L + case 0x86: + i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0); + break; // ADD M + case 0xC6: i8080_add(c, &c->a, i8080_next_byte(c), 0); break; // ADI byte + + case 0x8F: i8080_add(c, &c->a, c->a, c->cf); break; // ADC A + case 0x88: i8080_add(c, &c->a, c->b, c->cf); break; // ADC B + case 0x89: i8080_add(c, &c->a, c->c, c->cf); break; // ADC C + case 0x8A: i8080_add(c, &c->a, c->d, c->cf); break; // ADC D + case 0x8B: i8080_add(c, &c->a, c->e, c->cf); break; // ADC E + case 0x8C: i8080_add(c, &c->a, c->h, c->cf); break; // ADC H + case 0x8D: i8080_add(c, &c->a, c->l, c->cf); break; // ADC L + case 0x8E: + i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf); + break; // ADC M + case 0xCE: i8080_add(c, &c->a, i8080_next_byte(c), c->cf); break; // ACI byte + + case 0x97: i8080_sub(c, &c->a, c->a, 0); break; // SUB A + case 0x90: i8080_sub(c, &c->a, c->b, 0); break; // SUB B + case 0x91: i8080_sub(c, &c->a, c->c, 0); break; // SUB C + case 0x92: i8080_sub(c, &c->a, c->d, 0); break; // SUB D + case 0x93: i8080_sub(c, &c->a, c->e, 0); break; // SUB E + case 0x94: i8080_sub(c, &c->a, c->h, 0); break; // SUB H + case 0x95: i8080_sub(c, &c->a, c->l, 0); break; // SUB L + case 0x96: + i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0); + break; // SUB M + case 0xD6: i8080_sub(c, &c->a, i8080_next_byte(c), 0); break; // SUI byte + + case 0x9F: i8080_sub(c, &c->a, c->a, c->cf); break; // SBB A + case 0x98: i8080_sub(c, &c->a, c->b, c->cf); break; // SBB B + case 0x99: i8080_sub(c, &c->a, c->c, c->cf); break; // SBB C + case 0x9A: i8080_sub(c, &c->a, c->d, c->cf); break; // SBB D + case 0x9B: i8080_sub(c, &c->a, c->e, c->cf); break; // SBB E + case 0x9C: i8080_sub(c, &c->a, c->h, c->cf); break; // SBB H + case 0x9D: i8080_sub(c, &c->a, c->l, c->cf); break; // SBB L + case 0x9E: + i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf); + break; // SBB M + case 0xDE: i8080_sub(c, &c->a, i8080_next_byte(c), c->cf); break; // SBI byte + + case 0x09: i8080_dad(c, i8080_get_bc(c)); break; // DAD B + case 0x19: i8080_dad(c, i8080_get_de(c)); break; // DAD D + case 0x29: i8080_dad(c, i8080_get_hl(c)); break; // DAD H + case 0x39: i8080_dad(c, c->sp); break; // DAD SP + + case 0xF3: c->iff = 0; break; // DI + case 0xFB: + c->iff = 1; + c->interrupt_delay = 1; + break; // EI + case 0x00: break; // NOP + case 0x76: c->halted = 1; break; // HLT + + case 0x3C: c->a = i8080_inr(c, c->a); break; // INR A + case 0x04: c->b = i8080_inr(c, c->b); break; // INR B + case 0x0C: c->c = i8080_inr(c, c->c); break; // INR C + case 0x14: c->d = i8080_inr(c, c->d); break; // INR D + case 0x1C: c->e = i8080_inr(c, c->e); break; // INR E + case 0x24: c->h = i8080_inr(c, c->h); break; // INR H + case 0x2C: c->l = i8080_inr(c, c->l); break; // INR L + case 0x34: + i8080_wb(c, i8080_get_hl(c), i8080_inr(c, i8080_rb(c, i8080_get_hl(c)))); + break; // INR M + + case 0x3D: c->a = i8080_dcr(c, c->a); break; // DCR A + case 0x05: c->b = i8080_dcr(c, c->b); break; // DCR B + case 0x0D: c->c = i8080_dcr(c, c->c); break; // DCR C + case 0x15: c->d = i8080_dcr(c, c->d); break; // DCR D + case 0x1D: c->e = i8080_dcr(c, c->e); break; // DCR E + case 0x25: c->h = i8080_dcr(c, c->h); break; // DCR H + case 0x2D: c->l = i8080_dcr(c, c->l); break; // DCR L + case 0x35: + i8080_wb(c, i8080_get_hl(c), i8080_dcr(c, i8080_rb(c, i8080_get_hl(c)))); + break; // DCR M + + case 0x03: i8080_set_bc(c, i8080_get_bc(c) + 1); break; // INX B + case 0x13: i8080_set_de(c, i8080_get_de(c) + 1); break; // INX D + case 0x23: i8080_set_hl(c, i8080_get_hl(c) + 1); break; // INX H + case 0x33: c->sp += 1; break; // INX SP + + case 0x0B: i8080_set_bc(c, i8080_get_bc(c) - 1); break; // DCX B + case 0x1B: i8080_set_de(c, i8080_get_de(c) - 1); break; // DCX D + case 0x2B: i8080_set_hl(c, i8080_get_hl(c) - 1); break; // DCX H + case 0x3B: c->sp -= 1; break; // DCX SP + + case 0x27: i8080_daa(c); break; // DAA + case 0x2F: c->a = ~c->a; break; // CMA + case 0x37: c->cf = 1; break; // STC + case 0x3F: c->cf = !c->cf; break; // CMC + + case 0x07: i8080_rlc(c); break; // RLC (rotate left) + case 0x0F: i8080_rrc(c); break; // RRC (rotate right) + case 0x17: i8080_ral(c); break; // RAL + case 0x1F: i8080_rar(c); break; // RAR + + case 0xA7: i8080_ana(c, c->a); break; // ANA A + case 0xA0: i8080_ana(c, c->b); break; // ANA B + case 0xA1: i8080_ana(c, c->c); break; // ANA C + case 0xA2: i8080_ana(c, c->d); break; // ANA D + case 0xA3: i8080_ana(c, c->e); break; // ANA E + case 0xA4: i8080_ana(c, c->h); break; // ANA H + case 0xA5: i8080_ana(c, c->l); break; // ANA L + case 0xA6: i8080_ana(c, i8080_rb(c, i8080_get_hl(c))); break; // ANA M + case 0xE6: i8080_ana(c, i8080_next_byte(c)); break; // ANI byte + + case 0xAF: i8080_xra(c, c->a); break; // XRA A + case 0xA8: i8080_xra(c, c->b); break; // XRA B + case 0xA9: i8080_xra(c, c->c); break; // XRA C + case 0xAA: i8080_xra(c, c->d); break; // XRA D + case 0xAB: i8080_xra(c, c->e); break; // XRA E + case 0xAC: i8080_xra(c, c->h); break; // XRA H + case 0xAD: i8080_xra(c, c->l); break; // XRA L + case 0xAE: i8080_xra(c, i8080_rb(c, i8080_get_hl(c))); break; // XRA M + case 0xEE: i8080_xra(c, i8080_next_byte(c)); break; // XRI byte + + case 0xB7: i8080_ora(c, c->a); break; // ORA A + case 0xB0: i8080_ora(c, c->b); break; // ORA B + case 0xB1: i8080_ora(c, c->c); break; // ORA C + case 0xB2: i8080_ora(c, c->d); break; // ORA D + case 0xB3: i8080_ora(c, c->e); break; // ORA E + case 0xB4: i8080_ora(c, c->h); break; // ORA H + case 0xB5: i8080_ora(c, c->l); break; // ORA L + case 0xB6: i8080_ora(c, i8080_rb(c, i8080_get_hl(c))); break; // ORA M + case 0xF6: i8080_ora(c, i8080_next_byte(c)); break; // ORI byte + + case 0xBF: i8080_cmp(c, c->a); break; // CMP A + case 0xB8: i8080_cmp(c, c->b); break; // CMP B + case 0xB9: i8080_cmp(c, c->c); break; // CMP C + case 0xBA: i8080_cmp(c, c->d); break; // CMP D + case 0xBB: i8080_cmp(c, c->e); break; // CMP E + case 0xBC: i8080_cmp(c, c->h); break; // CMP H + case 0xBD: i8080_cmp(c, c->l); break; // CMP L + case 0xBE: i8080_cmp(c, i8080_rb(c, i8080_get_hl(c))); break; // CMP M + case 0xFE: i8080_cmp(c, i8080_next_byte(c)); break; // CPI byte + + case 0xC3: i8080_jmp(c, i8080_next_word(c)); break; // JMP + case 0xC2: i8080_cond_jmp(c, c->zf == 0); break; // JNZ + case 0xCA: i8080_cond_jmp(c, c->zf == 1); break; // JZ + case 0xD2: i8080_cond_jmp(c, c->cf == 0); break; // JNC + case 0xDA: i8080_cond_jmp(c, c->cf == 1); break; // JC + case 0xE2: i8080_cond_jmp(c, c->pf == 0); break; // JPO + case 0xEA: i8080_cond_jmp(c, c->pf == 1); break; // JPE + case 0xF2: i8080_cond_jmp(c, c->sf == 0); break; // JP + case 0xFA: i8080_cond_jmp(c, c->sf == 1); break; // JM + + case 0xE9: c->pc = i8080_get_hl(c); break; // PCHL + case 0xCD: i8080_call(c, i8080_next_word(c)); break; // CALL + + case 0xC4: i8080_cond_call(c, c->zf == 0); break; // CNZ + case 0xCC: i8080_cond_call(c, c->zf == 1); break; // CZ + case 0xD4: i8080_cond_call(c, c->cf == 0); break; // CNC + case 0xDC: i8080_cond_call(c, c->cf == 1); break; // CC + case 0xE4: i8080_cond_call(c, c->pf == 0); break; // CPO + case 0xEC: i8080_cond_call(c, c->pf == 1); break; // CPE + case 0xF4: i8080_cond_call(c, c->sf == 0); break; // CP + case 0xFC: i8080_cond_call(c, c->sf == 1); break; // CM + + case 0xC9: i8080_ret(c); break; // RET + case 0xC0: i8080_cond_ret(c, c->zf == 0); break; // RNZ + case 0xC8: i8080_cond_ret(c, c->zf == 1); break; // RZ + case 0xD0: i8080_cond_ret(c, c->cf == 0); break; // RNC + case 0xD8: i8080_cond_ret(c, c->cf == 1); break; // RC + case 0xE0: i8080_cond_ret(c, c->pf == 0); break; // RPO + case 0xE8: i8080_cond_ret(c, c->pf == 1); break; // RPE + case 0xF0: i8080_cond_ret(c, c->sf == 0); break; // RP + case 0xF8: i8080_cond_ret(c, c->sf == 1); break; // RM + + case 0xC7: i8080_call(c, 0x00); break; // RST 0 + case 0xCF: i8080_call(c, 0x08); break; // RST 1 + case 0xD7: i8080_call(c, 0x10); break; // RST 2 + case 0xDF: i8080_call(c, 0x18); break; // RST 3 + case 0xE7: i8080_call(c, 0x20); break; // RST 4 + case 0xEF: i8080_call(c, 0x28); break; // RST 5 + case 0xF7: i8080_call(c, 0x30); break; // RST 6 + case 0xFF: i8080_call(c, 0x38); break; // RST 7 + + case 0xC5: i8080_push_stack(c, i8080_get_bc(c)); break; // PUSH B + case 0xD5: i8080_push_stack(c, i8080_get_de(c)); break; // PUSH D + case 0xE5: i8080_push_stack(c, i8080_get_hl(c)); break; // PUSH H + case 0xF5: i8080_push_psw(c); break; // PUSH PSW + case 0xC1: i8080_set_bc(c, i8080_pop_stack(c)); break; // POP B + case 0xD1: i8080_set_de(c, i8080_pop_stack(c)); break; // POP D + case 0xE1: i8080_set_hl(c, i8080_pop_stack(c)); break; // POP H + case 0xF1: i8080_pop_psw(c); break; // POP PSW + + case 0xDB: c->a = c->port_in(c->userdata, i8080_next_byte(c)); break; // IN + case 0xD3: c->port_out(c->userdata, i8080_next_byte(c), c->a); break; // OUT + + case 0x08: + case 0x10: + case 0x18: + case 0x20: + case 0x28: + case 0x30: + case 0x38: break; // undocumented NOPs + + case 0xD9: i8080_ret(c); break; // undocumented RET + + case 0xDD: + case 0xED: + { + if (opcode == 0xED) { + uint8_t data = i8080_next_byte(c); + if (data == 0xED) { + interrupt_808x(i8080_next_byte(c)); + break; + } else if (data == 0xFD) { + retem_i8080(); + break; + } + else { + i8080_call(c, (i8080_next_byte(c) << 8) | data); break; + } + } + } + case 0xFD: i8080_call(c, i8080_next_word(c)); break; // undocumented CALLs + + case 0xCB: i8080_jmp(c, i8080_next_word(c)); break; // undocumented JMP + } +} + +// initialises the emulator with default values +void i8080_init(i8080* const c) { + c->read_byte = NULL; + c->write_byte = NULL; + c->port_in = NULL; + c->port_out = NULL; + c->userdata = NULL; + + c->cyc = 0; + + c->pc = 0; + c->sp = 0; + + c->a = 0; + c->b = 0; + c->c = 0; + c->d = 0; + c->e = 0; + c->h = 0; + c->l = 0; + + c->sf = 0; + c->zf = 0; + c->hf = 0; + c->pf = 0; + c->cf = 0; + c->iff = 0; + + c->halted = 0; + c->interrupt_pending = 0; + c->interrupt_vector = 0; + c->interrupt_delay = 0; +} + +// executes one instruction +void i8080_step(i8080* const c) { + // interrupt processing: if an interrupt is pending and IFF is set, + // we execute the interrupt vector passed by the user. + if (c->interrupt_pending && c->iff && c->interrupt_delay == 0) { + c->interrupt_pending = 0; + c->iff = 0; + c->halted = 0; + + i8080_execute(c, c->interrupt_vector); + } else if (!c->halted) { + i8080_execute(c, i8080_next_byte(c)); + } +} + +// asks for an interrupt to be serviced +void i8080_interrupt(i8080* const c, uint8_t opcode) { + c->interrupt_pending = 1; + c->interrupt_vector = opcode; +} + +// outputs a debug trace of the emulator state to the standard output, +// including registers and flags +void i8080_debug_output(i8080* const c, bool print_disassembly) { + uint8_t f = 0; + f |= c->sf << 7; + f |= c->zf << 6; + f |= c->hf << 4; + f |= c->pf << 2; + f |= 1 << 1; // bit 1 is always 1 + f |= c->cf << 0; + + printf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, CYC: %lu", + c->pc, c->a << 8 | f, i8080_get_bc(c), i8080_get_de(c), i8080_get_hl(c), + c->sp, c->cyc); + + printf("\t(%02X %02X %02X %02X)", i8080_rb(c, c->pc), i8080_rb(c, c->pc + 1), + i8080_rb(c, c->pc + 2), i8080_rb(c, c->pc + 3)); + + if (print_disassembly) { + printf(" - %s", DISASSEMBLE_TABLE[i8080_rb(c, c->pc)]); + } + + printf("\n"); +} + +#undef SET_ZSP diff --git a/src/cpu/i8080.h b/src/cpu/i8080.h new file mode 100644 index 000000000..43406e43e --- /dev/null +++ b/src/cpu/i8080.h @@ -0,0 +1,35 @@ +#ifndef I8080_I8080_H_ +#define I8080_I8080_H_ + +#include +#include +#include + +typedef struct i8080 { + // memory + io interface + uint8_t (*read_byte)(void*, uint16_t); // user function to read from memory + void (*write_byte)(void*, uint16_t, uint8_t); // same for writing to memory + uint8_t (*read_byte_seg)(void*, uint16_t); // user function to read from memory (Code segment) + uint8_t (*port_in)(void*, uint8_t); // user function to read from port + void (*port_out)(void*, uint8_t, uint8_t); // same for writing to port + void* userdata; // user custom pointer + + unsigned long cyc; // cycle count + + uint16_t pc, sp; // program counter, stack pointer + uint8_t a, b, c, d, e, h, l; // registers + // flags: sign, zero, half-carry, parity, carry, interrupt flip-flop + bool sf : 1, zf : 1, hf : 1, pf : 1, cf : 1, iff : 1; + bool halted : 1; + + bool interrupt_pending : 1; + uint8_t interrupt_vector; + uint8_t interrupt_delay; +} i8080; + +void i8080_init(i8080* const c); +void i8080_step(i8080* const c); +void i8080_interrupt(i8080* const c, uint8_t opcode); +void i8080_debug_output(i8080* const c, bool print_disassembly); + +#endif // I8080_I8080_H_ diff --git a/src/include/86box/i8080.h b/src/include/86box/i8080.h deleted file mode 100644 index 9a25b5d1b..000000000 --- a/src/include/86box/i8080.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - * - * 8080 CPU emulation (header). - * - * - * - * Authors: Cacodemon345 - * - * Copyright 2022 Cacodemon345 - */ - -#include - -typedef struct i8080 { - union { - uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */ - struct { - uint8_t a; - uint8_t flags; - }; - }; - union { - uint16_t bc; - struct { - uint8_t b; - uint8_t c; - }; - }; - union { - uint16_t de; - struct { - uint8_t d; - uint8_t e; - }; - }; - union { - uint16_t hl; - struct { - uint8_t h; - uint8_t l; - }; - }; - uint16_t pc; - uint16_t sp; - uint16_t oldpc; - uint16_t ei; - uint32_t pmembase; - uint32_t dmembase; /* Base from where i8080 starts. */ - uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */ - uint16_t *cpu_flags; - void (*writemembyte)(uint32_t, uint8_t); - uint8_t (*readmembyte)(uint32_t); - void (*startclock)(void); - void (*endclock)(void); - void (*checkinterrupts)(void); - uint8_t (*fetchinstruction)(void *); -} i8080; - -#define C_FLAG_I8080 (1 << 0) -#define P_FLAG_I8080 (1 << 2) -#define AC_FLAG_I8080 (1 << 4) -#define Z_FLAG_I8080 (1 << 6) -#define S_FLAG_I8080 (1 << 7) From 2b107725bdc9a30f94d4af0b55483c37047744aa Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 20:17:13 +0600 Subject: [PATCH 133/158] Custom NMI handling for i8080 emulation --- src/cpu/808x.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 4ce1fa3b9..c07e583ae 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1179,6 +1179,11 @@ custom_nmi(void) uint16_t new_cs, new_ip; uint16_t tempf; + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + pclog("NMI# (CUTSOM)\n"); + } + cpu_state.eaaddr = 0x0002; old_cs = CS; access(5, 16); @@ -1196,6 +1201,8 @@ custom_nmi(void) tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; From 929a9fb25e4a6ce86dfa81305e63e4267545d444 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Wed, 26 Mar 2025 19:30:21 +0500 Subject: [PATCH 134/158] Network settings page redesign Co-Authored-By: cold-brewed <47337035+cold-brewed@users.noreply.github.com> --- src/qt/qt_settingsnetwork.cpp | 61 +++- src/qt/qt_settingsnetwork.ui | 606 ++++++++++++++++++---------------- 2 files changed, 369 insertions(+), 298 deletions(-) diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 2aa3705fd..a0acd7a3f 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -35,25 +35,58 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) for (int i = 0; i < NET_CARD_MAX; ++i) { auto *nic_cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); + + auto *intf_label = findChild(QString("interfaceLabel%1").arg(i + 1)); auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + auto *conf_btn = findChild(QString("pushButtonConf%1").arg(i + 1)); +// auto *net_type_conf_btn = findChild(QString("pushButtonNetTypeConf%1").arg(i + 1)); + + auto *vde_socket_label = findChild(QString("socketVDELabel%1").arg(i + 1)); auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); - int netType = net_type_cbox->currentData().toInt(); - bool adaptersEnabled = netType == NET_TYPE_NONE - || netType == NET_TYPE_SLIRP - || netType == NET_TYPE_VDE - || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0); + auto *option_list_label = findChild(QString("optionListLabel%1").arg(i + 1)); + auto *option_list_line = findChild(QString("optionListLine%1").arg(i + 1)); intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP); - nic_cbox->setEnabled(adaptersEnabled); - int netCard = nic_cbox->currentData().toInt(); - if ((i == 0) && (netCard == NET_INTERNAL)) - conf_btn->setEnabled(adaptersEnabled && machine_has_flags(machineId, MACHINE_NIC) && - device_has_config(machine_get_net_device(machineId))); - else - conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt())); - socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE); + conf_btn->setEnabled(network_card_has_config(nic_cbox->currentData().toInt())); +// net_type_conf_btn->setEnabled(network_type_has_config(netType)); + + // Option list label and line + option_list_label->setVisible(false); + option_list_line->setVisible(false); + + + // VDE + vde_socket_label->setVisible(false); + socket_line->setVisible(false); + + // PCAP + intf_cbox->setVisible(false); + intf_label->setVisible(false); + + // Don't enable anything unless there's a nic selected + if(nic_cbox->currentData().toInt() != 0) { + // Then only enable as needed based on network type + switch (net_type_cbox->currentData().toInt()) { + case NET_TYPE_VDE: + // option_list_label->setText("VDE Options"); + option_list_label->setVisible(true); + option_list_line->setVisible(true); + + vde_socket_label->setVisible(true); + socket_line->setVisible(true); + break; + case NET_TYPE_PCAP: + // option_list_label->setText("PCAP Options"); + option_list_label->setVisible(true); + option_list_line->setVisible(true); + + intf_cbox->setVisible(true); + intf_label->setVisible(true); + break; + } + } } } @@ -154,7 +187,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) } model->removeRows(0, removeRows); - cbox->setCurrentIndex(net_cards_conf[i].net_type); + cbox->setCurrentIndex(cbox->findData(net_cards_conf[i].net_type)); selectedRow = 0; diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 8f1eb5a79..741b60648 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -36,20 +36,7 @@ Network Card #1 - - - - - 0 - 0 - - - - Mode - - - - + 30 @@ -63,32 +50,6 @@ - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - @@ -101,23 +62,40 @@ - - - - 30 + + + + Qt::Vertical + + + 20 + 40 + + + + + + - + 0 0 - - QComboBox::AdjustToContents + + Mode - + + + + Qt::Horizontal + + + + @@ -130,21 +108,74 @@ + + + + Options + + + - + + + + 0 + 0 + + + + Interface + + + + + VDE Socket - + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + 127 - + + + + + 0 + 0 + + + + + + + + + Network Card #2 + + + Qt::Vertical @@ -157,13 +188,26 @@ - - - - - Network Card #2 - - + + + + + 0 + 0 + + + + Interface + + + + + + + Options + + + @@ -177,7 +221,7 @@ - + 30 @@ -190,33 +234,21 @@ - - - - - 0 - 0 - - + + - Interface + VDE Socket - - - - 30 - - - - 0 - 0 - + + + + Qt::Horizontal - + @@ -229,7 +261,20 @@ - + + + + + 0 + 0 + + + + Configure + + + + 30 @@ -245,40 +290,19 @@ - - - - Configure + + + + + + + + 0 + 0 + - - - - VDE Socket - - - - - - - 127 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -286,6 +310,69 @@ Network Card #3 + + + + 30 + + + + 0 + 0 + + + + + + + + VDE Socket + + + + + + + Options + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + + + + + 0 + 0 + + + + Interface + + + + + + + Qt::Horizontal + + + @@ -299,75 +386,7 @@ - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Adapter - - - - - - - 30 - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - - + @@ -380,21 +399,33 @@ - - + + + + + 0 + 0 + + - VDE Socket + Adapter - - - - 127 + + + + + + + + 0 + 0 + - + Qt::Vertical @@ -414,6 +445,13 @@ Network Card #4 + + + + Options + + + @@ -427,102 +465,7 @@ - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Interface - - - - - - - 30 - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Adapter - - - - - - - 30 - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - - - - - - 0 - 0 - - - - Configure - - - - - - - 127 - - - - - - - VDE Socket - - - - + Qt::Vertical @@ -535,6 +478,101 @@ + + + + VDE Socket + + + + + + + + 0 + 0 + + + + Adapter + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Interface + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 30 + + + + + + + 30 + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Configure + + + + + + + + + + + 0 + 0 + + + + From ad4e90e345308cdd186e3e5ce368aa11f1d41d0c Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 23:01:09 +0600 Subject: [PATCH 135/158] Finally fix RETEM --- src/cpu/808x.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index c07e583ae..ac23cd99a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -1158,11 +1158,20 @@ retem_i8080(void) { sync_from_i8080(); - cpu_state.pc = pop(); - CS = pop(); - cpu_state.flags = pop() | MD_FLAG; + prefetching = 0; + pfq_clear(); + + set_ip(pop()); + load_cs(pop()); + cpu_state.flags = pop(); + + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); cpu_md_write_disable = 1; + + noint = 1; + nmi_enable = 1; + pclog("RETEM mode\n"); } @@ -3298,7 +3307,7 @@ execx86(int cycs) noint = 1; nmi_enable = 1; if (is_nec && !(cpu_state.flags & MD_FLAG)) - sync_to_i8080(); + sync_to_i8080(); break; case 0xD0: From abbae5efd2b1732ceefb7af11effa757bfe5f034 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 26 Mar 2025 23:18:36 +0600 Subject: [PATCH 136/158] Cleanups --- src/cpu/808x.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index ac23cd99a..e98b7de3d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -229,6 +229,8 @@ sync_from_i8080(void) void sync_to_i8080(void) { + if (!is_nec) + return; emulated_processor.a = AL; emulated_processor.h = BH; emulated_processor.l = BL; @@ -1085,7 +1087,7 @@ interrupt(uint16_t addr) if (!(cpu_state.flags & MD_FLAG) && is_nec) { sync_from_i8080(); - pclog("CALLN/INT#/NMI#\n"); + x808x_log("CALLN/INT#/NMI#\n"); } addr <<= 2; @@ -1150,7 +1152,7 @@ interrupt_brkem(uint16_t addr) access(41, 16); push(&old_ip); sync_to_i8080(); - pclog("BRKEM mode\n"); + x808x_log("BRKEM mode\n"); } void @@ -1172,7 +1174,7 @@ retem_i8080(void) noint = 1; nmi_enable = 1; - pclog("RETEM mode\n"); + x808x_log("RETEM mode\n"); } void From 209b29a2390e343a31fe2890fa9b4ef3616e3ad2 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Mar 2025 00:55:33 +0900 Subject: [PATCH 137/158] PS55DA2: cleanup, change func scope remove unused variables, change funcs declaration scope, reformat debug code --- src/video/vid_ps55da2.c | 172 +++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 91 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index af8beddb9..158629226 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -29,7 +29,6 @@ #include #include #include -#include #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> @@ -40,7 +39,6 @@ #include <86box/mca.h> #include <86box/rom.h> #include <86box/plat.h> -#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_ps55da2.h> #include <86box/vid_svga.h> @@ -256,8 +254,9 @@ #endif #ifdef ENABLE_DA2_LOG +// # define ENABLE_DA2_DEBUGIO 1 // # define ENABLE_DA2_DEBUGBLT 1 -# define ENABLE_DA2_DEBUGVRAM 1 +// # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -276,6 +275,11 @@ da2_log(const char *fmt, ...) #else # define da2_log(fmt, ...) #endif +#ifdef ENABLE_DA2_DEBUGIO +# define da2_iolog da2_log +#else +# define da2_iolog(fmt, ...) +#endif #ifdef ENABLE_DA2_DEBUGBLT # define da2_bltlog da2_log #else @@ -302,9 +306,6 @@ typedef struct da2_t { int fctladdr; int crtcaddr; - uint32_t decode_mask; - uint32_t vram_max; - uint32_t gdcla[8]; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; @@ -317,13 +318,8 @@ typedef struct da2_t { uint8_t plane_mask; - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; + int writemode, readplane; uint8_t planemask; - uint32_t charseta, charsetb; uint8_t egapal[16]; uint32_t pallook[512]; @@ -357,13 +353,9 @@ typedef struct da2_t { /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; - /* (cram size - 1) >> 3 = 0xFFF */ - // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; - /* xxh */ uint8_t *changedvram; - /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; int fullchange; @@ -374,7 +366,6 @@ typedef struct da2_t { card should not attempt to display anything */ int override; - /* end VGA compatible regs*/ struct { int enable; @@ -431,13 +422,13 @@ typedef struct da2_t { int old_pos2; } da2_t; -void da2_recalctimings(da2_t *da2); -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); -void da2_bitblt_exec(void *p); -void da2_updatevidselector(da2_t *da2); -void da2_reset_ioctl(da2_t *da2); -static void da2_reset(void *priv); -uint16_t rightRotate(uint16_t data, uint8_t count); +static void da2_recalctimings(da2_t *da2); +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); +static void da2_bitblt_exec(void *p); +static void da2_updatevidselector(da2_t *da2); +static void da2_reset_ioctl(da2_t *da2); +static void da2_reset(void *priv); +static uint16_t rightRotate(uint16_t data, uint8_t count); typedef union { uint32_t d; @@ -449,7 +440,7 @@ typedef struct { } pixel32; /* safety read for internal functions */ -uint32_t +static uint32_t DA2_vram_r(uint32_t addr, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) @@ -457,7 +448,7 @@ DA2_vram_r(uint32_t addr, da2_t *da2) return da2->vram[addr]; } /* safety write for internal functions */ -void +static void DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) { if (addr & ~DA2_MASK_VRAM) @@ -466,7 +457,7 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) return; } /* write pixel data with rop (Note: bitmask must be in big endian) */ -void +static void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { uint32_t writepx[8]; @@ -516,7 +507,7 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s } } -void +static void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -554,7 +545,7 @@ Param Desc 33 Size W 35 Size H */ -void +static void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -568,7 +559,7 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } -void +static void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; @@ -655,7 +646,7 @@ IBMJtoSJIS(uint16_t knj) return knj; } #endif -void +static void da2_bitblt_load(da2_t *da2) { uint32_t value32; @@ -892,7 +883,7 @@ da2_bitblt_load(da2_t *da2) } } } -void +static void da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; @@ -1099,7 +1090,7 @@ da2_bitblt_exec(void *p) break; } } -void +static void da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -1116,7 +1107,7 @@ da2_bitblt_dopayload(void *priv) } } -void +static void da2_out(uint16_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; @@ -1142,7 +1133,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->dac_pos = 0; break; case 0x3C9: /* Data */ - // da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); + // da2_iolog("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); da2->dac_status = 0; da2->fullchange = changeframecount; switch (da2->dac_pos) { @@ -1171,11 +1162,11 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->ioctladdr = val; break; case LS_DATA: - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); if (da2->ioctladdr > 0xf) return; if (da2->ioctl[da2->ioctladdr & 15] != val) - da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); + da2_iolog("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { @@ -1192,15 +1183,15 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->fctladdr = val; break; case LF_DATA: - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); if (da2->fctladdr > 0x1f) return; if (da2->fctl[da2->fctladdr & 0x1f] != val) - da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); + da2_iolog("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { - da2_log("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); } break; case LC_INDEX: @@ -1210,7 +1201,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) if (da2->crtcaddr > 0x1f) return; if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { @@ -1261,7 +1252,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) } break; case LV_PORT: - // da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); if (!da2->attrff) { // da2->attraddr = val & 31; da2->attraddr = val & 0x3f; @@ -1270,14 +1261,14 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->attr_palette_enable = val & 0x20; da2_recalctimings(da2); } - // da2_log("set attraddr: %X\n", da2->attraddr); + // da2_iolog("set attraddr: %X\n", da2->attraddr); } else { if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) da2->fullchange = changeframecount; if (da2->attrc[da2->attraddr & 0x3f] != val) - da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); + da2_iolog("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); da2->attrc[da2->attraddr & 0x3f] = val; - // da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); + // da2_iolog("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) da2->fullchange = changeframecount; if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { @@ -1325,12 +1316,12 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->attrc[da2->attraddr & 0x3f] = val; break; case LG_INDEX: - da2_log("DA2 Out addr %03X val %02X\n", addr, val); + da2_iolog("DA2 Out addr %03X val %02X\n", addr, val); da2->gdcaddr = val; break; case LG_DATA: - // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); - da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_iolog("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + da2_iolog("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: @@ -1350,7 +1341,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LG_COMMAND: break; case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + da2_iolog("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } break; @@ -1358,12 +1349,12 @@ da2_out(uint16_t addr, uint16_t val, void *p) // da2->gdcreg[5] = val & 0xff; // break; default: - da2_log("DA2? Out addr %03X val %02X\n", addr, val); + da2_iolog("DA2? Out addr %03X val %02X\n", addr, val); break; } } -uint16_t +static uint16_t da2_in(uint16_t addr, void *p) { da2_t *da2 = (da2_t *) p; @@ -1431,17 +1422,17 @@ da2_in(uint16_t addr, void *p) // if (da2->bitblt.indata) /* for OS/2 J1.3 command prompt scrolling */ // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { - // da2_log("exec:%x\n", da2->bitblt.exec); + // da2_iolog("exec:%x\n", da2->bitblt.exec); temp |= 0x01; /* wait (bit 3 + bit 0) ? need verify */ // if (!da2->bitblt.timer.enabled) //{ - // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); + // da2_iolog("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } if (da2->bitblt.indata) temp |= 0x08; #ifdef ENABLE_DA2_DEBUGMONWAIT - da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); + da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif } break; @@ -1474,7 +1465,7 @@ da2_in(uint16_t addr, void *p) temp = da2->cgastat; } else temp = da2->attrc[da2->attraddr]; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ break; case LG_INDEX: @@ -1482,10 +1473,10 @@ da2_in(uint16_t addr, void *p) break; case LG_DATA: temp = da2->gdcreg[da2->gdcaddr & 0x1f]; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); break; } - // da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } /* @@ -1499,11 +1490,11 @@ da2_in(uint16_t addr, void *p) * out b(idx), in b, in b(data) * out b(idx), in w(data) */ -void +static void da2_outb(uint16_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; - // da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + // da2_iolog("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); da2->inflipflop = 0; switch (addr) { case LS_DATA: @@ -1533,7 +1524,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p) void da2_outw(uint16_t addr, uint16_t val, void *p) { - da2_log("DA2 Outw addr %03X val %04X\n", addr, val); + da2_iolog("DA2 Outw addr %03X val %04X\n", addr, val); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1553,8 +1544,8 @@ da2_outw(uint16_t addr, uint16_t val, void *p) da2->outflipflop = 0; break; case 0x3EC: - // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_log(" "); + // da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog(" "); // val = rightRotate(val, 8); // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); @@ -1580,12 +1571,12 @@ da2_outw(uint16_t addr, uint16_t val, void *p) break; case AC_REG: /* no register is revealed */ - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2->reg3ee[val & 0x0f] = val >> 8; break; } } -uint8_t +static uint8_t da2_inb(uint16_t addr, void *p) { uint8_t temp; @@ -1615,10 +1606,10 @@ da2_inb(uint16_t addr, void *p) da2->inflipflop = 0; break; } - // da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -uint16_t +static uint16_t da2_inw(uint16_t addr, void *p) { uint16_t temp; @@ -1626,11 +1617,11 @@ da2_inw(uint16_t addr, void *p) da2->inflipflop = 0; da2->outflipflop = 0; temp = da2_in(addr, da2); - da2_log("DA2 Inw addr %03X val %04X\n", addr, temp); + da2_iolog("DA2 Inw addr %03X val %04X\n", addr, temp); return temp; } /* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ -uint8_t +static uint8_t da2_in_ISR(uint16_t addr, void *p) { da2_t *da2 = (da2_t *) p; @@ -1642,15 +1633,15 @@ da2_in_ISR(uint16_t addr, void *p) da2->cgastat ^= 0x30; temp = da2->cgastat; } - // da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_iolog("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -void +static void da2_out_ISR(uint16_t addr, uint8_t val, void *p) { // da2_t* da2 = (da2_t*)p; - da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_iolog("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); } /* @@ -1754,7 +1745,7 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. */ /* Get character line pattern from jfont rom or gaiji volatile memory */ -uint32_t +static uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void *p) { da2_t *da2 = (da2_t *) p; @@ -1792,14 +1783,14 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *p) } /* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ -uint8_t +static int8_t IRGBtoBGRI(uint8_t attr) { attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); return attr >>= 4; } /* Get the foreground color from the attribute byte */ -uint8_t +static uint8_t getPS55ForeColor(uint8_t attr, da2_t *da2) { uint8_t foreground = ~attr & 0x08; /* 0000 1000 */ @@ -1811,7 +1802,7 @@ getPS55ForeColor(uint8_t attr, da2_t *da2) return foreground; } -void +static void da2_render_blank(da2_t *da2) { int x, xx; @@ -2062,7 +2053,7 @@ da2_render_textm3(da2_t *da2) } } -void +static void da2_render_color_4bpp(da2_t *da2) { int changed_offset = da2->ma >> 9; @@ -2111,7 +2102,7 @@ da2_render_color_4bpp(da2_t *da2) } } -void +static void da2_render_color_8bpp(da2_t *da2) { int changed_offset = da2->ma >> 9; @@ -2160,7 +2151,7 @@ da2_render_color_8bpp(da2_t *da2) } } -void +static void da2_updatevidselector_tick(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -2176,7 +2167,7 @@ da2_updatevidselector_tick(void *priv) } } -void +static void da2_updatevidselector(da2_t *da2) { timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); @@ -2194,7 +2185,7 @@ da2_updatevidselector(da2_t *da2) 45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp 46h(undoc) APA 16 ? A0000h 1040 x 768 color_4bpp */ -void +static void da2_recalctimings(da2_t *da2) { double crtcconst; @@ -2298,8 +2289,7 @@ da2_recalctimings(da2_t *da2) da2->dispofftime = TIMER_USEC; da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock); da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); - + da2_log("da2 dispon %lu dispoff %lu on(us) %f off(us) %f\n",da2->dispontime, da2->dispofftime, (double)da2->dispontime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0, (double)da2->dispofftime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0); // da2_log("da2->render %08X\n", da2->render); } @@ -2334,14 +2324,14 @@ da2_mapping_update(da2_t *da2) } } -uint8_t +static uint8_t da2_mca_read(int port, void *p) { da2_t *da2 = (da2_t *) p; return da2->pos_regs[port & 7]; } -void +static void da2_mca_write(int port, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; @@ -2702,7 +2692,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->fullchange = 2; } } -uint16_t +static uint16_t rightRotate(uint16_t data, uint8_t count) { return (data >> count) | (data << (sizeof(data) * 8 - count)); @@ -2875,7 +2865,7 @@ da2_code_readw(uint32_t addr, void *p) return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); } -void +static void da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { @@ -2894,7 +2884,7 @@ da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) video_bpp = 8; } -void +static void da2_poll(void *priv) { da2_t *da2 = (da2_t *) priv; @@ -3090,7 +3080,7 @@ static uint8_t ps55_palette_color[64][3] = { { 0x3F, 0x15, 0x15 }, { 0x3F, 0x15, 0x3F }, { 0x3F, 0x3F, 0x15 }, { 0x3F, 0x3F, 0x3F } }; -void +static void da2_reset_ioctl(da2_t *da2) { da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ @@ -3204,7 +3194,7 @@ da2_available(void) return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } -void +static void da2_close(void *p) { da2_t *da2 = (da2_t *) p; @@ -3292,7 +3282,7 @@ da2_close(void *p) free(da2); } -void +static void da2_speed_changed(void *p) { da2_t *da2 = (da2_t *) p; @@ -3300,7 +3290,7 @@ da2_speed_changed(void *p) da2_recalctimings(da2); } -void +static void da2_force_redraw(void *p) { da2_t *da2 = (da2_t *) p; From da855e02b4219bdda33325c0caa557ffc4ee2c99 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Mar 2025 01:30:00 +0900 Subject: [PATCH 138/158] PS55DA2: Fix video switcher Fix an issue that the screen is resized repeatedly when booting OS/2. --- src/video/vid_ps55da2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 158629226..98db5f9fa 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1242,7 +1242,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_VERTICAL_SYNC_START: case LC_V_DISPLAY_ENABLE_END: case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: + case LC_START_H_DISPLAY_ENAB: + case LC_START_V_DISPLAY_ENAB: case LC_VIEWPORT_PRIORITY: da2->fullchange = changeframecount; da2_recalctimings(da2); @@ -2158,10 +2159,12 @@ da2_updatevidselector_tick(void *priv) if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; + timer_disable(&da2->timer); svga_set_override(da2->mb_vga, 0); da2_log("DA2 selector: VGA\n"); } else { svga_set_override(da2->mb_vga, 1); + timer_enable(&da2->timer); da2->override = 0; da2_log("DA2 selector: DA2\n"); } @@ -2310,12 +2313,10 @@ da2_mapping_update(da2_t *da2) io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); mem_mapping_enable(&da2->cmapping); mem_mapping_enable(&da2->mmio.mapping); - timer_enable(&da2->timer); timer_enable(&da2->bitblt.timer); } else { da2_log("DA2 disable registers\n"); timer_disable(&da2->bitblt.timer); - timer_disable(&da2->timer); mem_mapping_disable(&da2->cmapping); mem_mapping_disable(&da2->mmio.mapping); io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); From 93f3e9f339361dbdecc2fbc0a87c9b7c31e9dd97 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Mar 2025 19:10:20 +0100 Subject: [PATCH 139/158] Keyboard: Actually reset everything in keyboard_init() and call it in pc_reset_hard_init() as well. --- src/device/keyboard.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 58d5a4724..a00968cf7 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -113,7 +113,17 @@ static scconvtbl scconv55_8a[18 + 1] = void keyboard_init(void) { + num_lock = 0; + caps_lock = 0; + scroll_lock = 0; + shift = 0; + memset(recv_key, 0x00, sizeof(recv_key)); + memset(recv_key_ui, 0x00, sizeof(recv_key)); + memset(oldkey, 0x00, sizeof(recv_key)); +#if 0 + memset(key_delay, 0x00, sizeof(recv_key)); +#endif keyboard_scan = 1; scan_table = NULL; From ffd00e4527f56f429b8c826343c0de08f166ef6b Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 27 Mar 2025 19:14:01 +0100 Subject: [PATCH 140/158] Forgot 86box.c. --- src/86box.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/86box.c b/src/86box.c index dbf58a70e..2b6e1ba9f 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1293,6 +1293,8 @@ pc_reset_hard_init(void) * modules that are. */ + keyboard_init(); + /* Reset the IDE and SCSI presences */ other_ide_present = other_scsi_present = 0; From cec630fa756874bdf2ccc4a6fb3b733df2b4ad52 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 03:26:28 +0100 Subject: [PATCH 141/158] JEGA: Use colors based on a photo of the real OKI IF386AX when the LCD is in use to tell it apart more easily, and reset all devices on port 65h reset, fixes Trantor SCSI BIOS not finding any devices after such a reset. --- src/video/vid_jega.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 36cf04077..d8994916f 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -770,6 +770,8 @@ if386_p6x_read(uint16_t port, void *priv) Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21) Bit 3: ? */ +static uint32_t lcd_cols[8] = { 0x001024, 0x747d8a, 0x8c96a4, 0xa0abbb, + 0xb1bece, 0xc0cee0, 0xceddf0, 0xdbebff }; static void if386_p6x_write(uint16_t port, uint8_t val, void *priv) { @@ -793,19 +795,31 @@ if386_p6x_write(uint16_t port, uint8_t val, void *priv) } else { /* Monochrome LCD */ for (int c = 0; c < 256; c++) { int cval = 0; +#ifdef SIMPLE_BW if (c & 0x0f) cval = ((c & 0x0e) * 0x10) + 0x1f; pallook64[c] = makecol32(cval, cval, cval); pallook16[c] = makecol32(cval, cval, cval); +#else + if (c & 0x3f) { + cval = (c & 0x10) >> 2; + cval |= (c & 0x06) >> 1; + } + pallook64[c] = lcd_cols[cval]; + cval = 0; + if (c & 0x0f) + cval = (c & 0x0e) >> 1; + pallook16[c] = lcd_cols[cval]; +#endif } } jega_recalctimings(jega); } else if (p65idx == 0x05) { - if (val & 0x10) + if (val & 0x10) { /* Power off (instead this call hardware reset here) */ + device_reset_all(DEVICE_ALL); resetx86(); - /* Actually, power off - we have a function for that! */ - // plat_power_off(); + } } } return; From 8a8ed6004383dbe271f6b7db01c0d29baeaeec11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 03:29:11 +0100 Subject: [PATCH 142/158] EGA: Send monochrome attributes through the EGA palette lookup like the real hardware also does. --- src/video/vid_ega_render.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index dd393e4b6..261474742 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -181,6 +181,7 @@ ega_render_text(ega_t *ega) p[xx] = ega->mdacols[attr][attrblink][1]; else p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; + p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]]; } else p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; } @@ -189,9 +190,6 @@ ega_render_text(ega_t *ega) p += charwidth; } ega->ma &= 0x3ffff; - - if (monoattrs) - video_process_8(ega->hdisp + ega->scrollcache, ega->displine); } } From 63222b70db1e8ad5f1d651d6dce8e6c3a511d50b Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:16:05 +0100 Subject: [PATCH 143/158] Added the OKIVGA/H-2 (JVGA/H). --- src/include/86box/vid_ega.h | 9 +- src/include/86box/vid_svga.h | 5 + src/include/86box/vid_vga.h | 15 +- src/video/vid_ega.c | 2 +- src/video/vid_jega.c | 354 ++++++++++++++++++++++++----------- src/video/vid_svga.c | 5 +- src/video/vid_table.c | 1 + src/video/vid_vga.c | 45 +++-- 8 files changed, 293 insertions(+), 143 deletions(-) diff --git a/src/include/86box/vid_ega.h b/src/include/86box/vid_ega.h index 5ac5c24e3..0e28820ff 100644 --- a/src/include/86box/vid_ega.h +++ b/src/include/86box/vid_ega.h @@ -144,10 +144,10 @@ typedef struct ega_t { uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr); void (*render)(struct ega_t *svga); - /*If set then another device is driving the monitor output and the EGA - card should not attempt to display anything */ - void (*render_override)(void *priv); - void *priv_parent; + /* If set then another device is driving the monitor output and the EGA + card should not attempt to display anything. */ + void (*render_override)(void *priv); + void * priv_parent; } ega_t; #endif @@ -159,6 +159,7 @@ extern const device_t atiega800p_device; extern const device_t iskra_ega_device; extern const device_t et2000_device; extern const device_t jega_device; +extern const device_t jvga_device; #endif extern int update_overscan; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index afff6e211..068774eac 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -310,6 +310,11 @@ typedef struct svga_t { void * ext8514; void * clock_gen8514; void * xga; + + /* If set then another device is driving the monitor output and the EGA + card should not attempt to display anything. */ + void (*render_override)(void *priv); + void * priv_parent; } svga_t; extern void ibm8514_set_poll(svga_t *svga); diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index 26b5a7f71..54a1d0690 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -25,14 +25,19 @@ typedef struct vga_t { svga_t svga; - rom_t bios_rom; + rom_t bios_rom; } vga_t; -extern void vga_out(uint16_t addr, uint8_t val, void *priv); +extern void vga_out(uint16_t addr, uint8_t val, void *priv); extern uint8_t vga_in(uint16_t addr, void *priv); -void vga_disable(void* p); -void vga_enable(void* p); -int vga_isenabled(void* p); +extern void vga_init(const device_t *info, vga_t *vga, int enabled); + +extern void vga_disable(void* p); +extern void vga_enable(void* p); + +extern int vga_isenabled(void* p); + +extern video_timings_t timing_vga; #endif /*VIDEO_VGA_H*/ diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 16a3552ad..17b3fb593 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -780,7 +780,7 @@ ega_poll(void *priv) ega->y_add *= ega->vres + 1; for (y = 0; y <= ega->vres; y++) { /* Render scanline */ - if(ega->render_override) + if (ega->render_override) ega->render_override(ega->priv_parent); else ega->render(ega); diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index d8994916f..af20444dd 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -34,6 +34,8 @@ #include <86box/device.h> #include <86box/video.h> #include <86box/vid_ega.h> +#include <86box/vid_svga.h> +#include <86box/vid_vga.h> /* JEGA internal registers */ #define RPESL 0x09 /* End Scan Line */ @@ -63,6 +65,8 @@ #define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" #define IF386_PATH_VBIOS "roms/machines/if386sx/OKI_IF386SX_VBIOS.bin" +#define JVGA_PATH_BIOS "roms/video/jega/OKI_JVGT(AXVGAH)_BIOS_011993.BIN" +#define JVGA_PATH_FONTDBCS "roms/video/jega/JWPCE.FNT" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 #define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2) @@ -96,29 +100,31 @@ jega_log(const char *fmt, ...) static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; typedef struct jega_t { - rom_t bios_rom; - ega_t ega; - uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */ - uint8_t regs[0x31]; - uint8_t egapal[16]; - uint8_t attrregs[32]; - uint8_t attraddr; - uint8_t attrff; - uint8_t attr_palette_enable; + rom_t bios_rom; + ega_t ega; + vga_t vga; + uint8_t regs_index; /* 3D4/3D5 index B9-BF, D9-DF */ + uint8_t regs[0x31]; + uint8_t egapal[16]; + uint8_t attrregs[32]; + uint8_t attraddr; + uint8_t attrff; + uint8_t attr_palette_enable; uint32_t *pallook; - int con; - int cursoron; - int cursorblink_disable; - int ca; - int font_index; - int sbcsbank_inv; - int attr3_sbcsbank; - int start_scan_lower; - int start_scan_upper; - int start_scan_count; - uint8_t *vram; - uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */ - uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */ + int is_vga; + int con; + int cursoron; + int cursorblink_disable; + int ca; + int font_index; + int sbcsbank_inv; + int attr3_sbcsbank; + int start_scan_lower; + int start_scan_upper; + int start_scan_count; + uint8_t * vram; + uint8_t jfont_sbcs_19[SBCS19_FILESIZE]; /* 8 x 19 font */ + uint8_t jfont_dbcs_16[DBCS16_FILESIZE]; /* 16 x 16 font. Use dbcs_read/write to access it. */ } jega_t; static void jega_recalctimings(void *priv); @@ -127,16 +133,16 @@ static void jega_recalctimings(void *priv); #define FONTX_LEN_FN 8 typedef struct { - char id[FONTX_LEN_ID]; - char name[FONTX_LEN_FN]; - unsigned char width; - unsigned char height; - unsigned char type; + char id[FONTX_LEN_ID]; + char name[FONTX_LEN_FN]; + uint8_t width; + uint8_t height; + uint8_t type; } fontx_h; typedef struct { - uint16_t start; - uint16_t end; + uint16_t start; + uint16_t end; } fontx_tbl; extern uint32_t pallook16[256]; @@ -147,22 +153,32 @@ static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr static uint16_t SJIS_to_SEQ(uint16_t sjis) { - uint32_t chr1 = (sjis >> 8) & 0xff; - uint32_t chr2 = sjis & 0xff; - if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) return INVALIDACCESS16; - chr1 -= 0x81; - if (chr1 > 0x5E) chr1 -= 0x40; - chr2 -= 0x40; - if (chr2 > 0x3F) chr2--; - chr1 *= 0xBC; - return (chr1 + chr2); + uint32_t chr1 = (sjis >> 8) & 0xff; + uint32_t chr2 = sjis & 0xff; + + if (!is_SJIS_1(chr1) || !is_SJIS_2(chr2)) + return INVALIDACCESS16; + + chr1 -= 0x81; + + if (chr1 > 0x5e) + chr1 -= 0x40; + + chr2 -= 0x40; + + if (chr2 > 0x3f) + chr2--; + + chr1 *= 0xbc; + + return (chr1 + chr2); } static uint8_t dbcs_read(uint16_t sjis, int index, void *priv) { jega_t *jega = (jega_t *) priv; int seq = SJIS_to_SEQ(sjis); - if (seq >= DBCS16_CHARS || index >= 32) + if ((seq >= DBCS16_CHARS) || (index >= 32)) return INVALIDACCESS8; return jega->jfont_dbcs_16[seq * 32 + index]; } @@ -171,7 +187,7 @@ static void dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) { jega_t *jega = (jega_t *) priv; int seq = SJIS_to_SEQ(sjis); - if (seq >= DBCS16_CHARS || index >= 32) + if ((seq >= DBCS16_CHARS) || (index >= 32)) return; jega->jfont_dbcs_16[seq * 32 + index] = val; } @@ -180,38 +196,81 @@ dbcs_write(uint16_t sjis, int index, uint8_t val, void *priv) { void jega_render_text(void *priv) { - jega_t *jega = (jega_t *) priv; - if (jega->ega.firstline_draw == 2000) - jega->ega.firstline_draw = jega->ega.displine; - jega->ega.lastline_draw = jega->ega.displine; + jega_t * jega = (jega_t *) priv; +#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS + uint8_t * seqregs = jega->is_vga ? jega->vga.svga.seqregs : + jega->ega.seqregs; + uint8_t * attrregs = jega->is_vga ? jega->vga.svga.attrregs : + jega->ega.attrregs; +#endif + uint8_t * crtc = jega->is_vga ? jega->vga.svga.crtc : + jega->ega.crtc; + uint8_t * vram = jega->is_vga ? jega->vga.svga.vram : + jega->ega.vram; + int * firstline_draw = jega->is_vga ? &jega->vga.svga.firstline_draw : + &jega->ega.firstline_draw; + int * lastline_draw = jega->is_vga ? &jega->vga.svga.lastline_draw : + &jega->ega.lastline_draw; + int * displine = jega->is_vga ? &jega->vga.svga.displine : + &jega->ega.displine; + int * fullchange = jega->is_vga ? &jega->vga.svga.fullchange : + &jega->ega.fullchange; + int * blink = jega->is_vga ? &jega->vga.svga.blink : + &jega->ega.blink; + int * x_add = jega->is_vga ? &jega->vga.svga.x_add : + &jega->ega.x_add; + int * y_add = jega->is_vga ? &jega->vga.svga.y_add : + &jega->ega.y_add; + int * sc = jega->is_vga ? &jega->vga.svga.sc : + &jega->ega.sc; + int * hdisp = jega->is_vga ? &jega->vga.svga.hdisp : + &jega->ega.hdisp; + int * scrollcache = jega->is_vga ? &jega->vga.svga.scrollcache : + &jega->ega.scrollcache; + uint32_t *ma = jega->is_vga ? &jega->vga.svga.ma : + &jega->ega.ma; + uint8_t mask = jega->is_vga ? jega->vga.svga.dac_mask : 0xff; - if (jega->ega.fullchange) { - // const bool doublewidth = ((jega->ega.seqregs[1] & 8) != 0); - const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ - // const bool attrlinechars = (jega->ega.attrregs[0x10] & 4); - const bool crtcreset = ((jega->ega.crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0); - const int charwidth = 8; - const bool blinked = jega->ega.blink & 0x10; - uint32_t *p = &buffer32->line[jega->ega.displine + jega->ega.y_add][jega->ega.x_add]; - bool chr_wide = false; - int sc_wide = jega->ega.sc - jega->start_scan_count; - const bool cursoron = (blinked || jega->cursorblink_disable) - && (jega->ega.sc >= jega->regs[RCCSL]) && (jega->ega.sc <= jega->regs[RCCEL]); - uint32_t chr_first; - uint32_t attr_basic; - int fg; - int bg; + if (*firstline_draw == 2000) + *firstline_draw = *displine; + *lastline_draw = *displine; - for (int x = 0; x < (jega->ega.hdisp + jega->ega.scrollcache); x += charwidth) { - uint32_t addr = jega->ega.remap_func(&jega->ega, jega->ega.ma) & jega->ega.vrammask; + if (*fullchange) { +#ifdef USE_DOUBLE_WIDTH_AND_LINE_CHARS + const bool doublewidth = ((seqregs[1] & 8) != 0); + const bool attrlinechars = (attrregs[0x10] & 4); +#endif + const bool attrblink = ((jega->regs[RMOD2] & 0x20) == 0); /* JEGA specific */ + const bool crtcreset = ((crtc[0x17] & 0x80) == 0) || ((jega->regs[RMOD1] & 0x80) == 0); + const int charwidth = 8; + const bool blinked = *blink & 0x10; + uint32_t *p = &buffer32->line[*displine + *y_add][*x_add]; + bool chr_wide = false; + int sc_wide = *sc - jega->start_scan_count; + const bool cursoron = (blinked || jega->cursorblink_disable) && + (*sc >= jega->regs[RCCSL]) && (*sc <= jega->regs[RCCEL]); + uint32_t chr_first; + uint32_t attr_basic; + int fg; + int bg; - int drawcursor = ((jega->ega.ma == jega->ca) && cursoron); + for (int x = 0; x < (*hdisp + *scrollcache); x += charwidth) { + uint32_t addr = 0; + + if (jega->is_vga) { + if (!jega->vga.svga.force_old_addr) + addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.ma) & + jega->vga.svga.vram_display_mask; + } else + addr = jega->ega.remap_func(&jega->ega, *ma) & jega->ega.vrammask; + + int drawcursor = ((*ma == jega->ca) && cursoron); uint32_t chr; uint32_t attr; if (!crtcreset) { - chr = jega->ega.vram[addr]; - attr = jega->ega.vram[addr + 1]; + chr = vram[addr]; + attr = vram[addr + 1]; } else chr = attr = 0; if (chr_wide) { @@ -222,13 +281,13 @@ jega_render_text(void *priv) /* Bold | 2x width | 2x height | U/L select | R/L select | - | - | - */ attr_ext = attr; if ((attr_ext & 0x30) == 0x30) - sc_wide = jega->ega.sc - jega->start_scan_lower; /* Set top padding of lower 2x character */ + sc_wide = *sc - jega->start_scan_lower; /* Set top padding of lower 2x character */ else if ((attr_ext & 0x30) == 0x20) - sc_wide = jega->ega.sc - jega->start_scan_upper; /* Set top padding of upper 2x character */ + sc_wide = *sc - jega->start_scan_upper; /* Set top padding of upper 2x character */ else - sc_wide = jega->ega.sc - jega->start_scan_count; + sc_wide = *sc - jega->start_scan_count; } - if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && jega->ega.sc <= jega->regs[RPESL]) { + if (is_SJIS_2(chr) && sc_wide >= 0 && sc_wide < 16 && *sc <= jega->regs[RPESL]) { chr_first <<= 8; chr |= chr_first; /* Vertical wide font (Extended Attribute) */ @@ -269,7 +328,7 @@ jega_render_text(void *priv) if (attr_basic & 0x20) { /* vertical line */ p[0] = fg; } - if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ for (int xx = 0; xx < charwidth * 2; xx++) p[xx] = fg; } @@ -298,13 +357,13 @@ jega_render_text(void *priv) /* Parse attribute as EGA */ /* BInt/Blink | BR | BG | BB | Int/Group | R | G | B */ if (drawcursor) { - bg = jega->pallook[jega->egapal[attr & 0x0f]]; - fg = jega->pallook[jega->egapal[attr >> 4]]; + bg = jega->pallook[jega->egapal[attr & 0x0f] & mask]; + fg = jega->pallook[jega->egapal[attr >> 4] & mask]; } else { - fg = jega->pallook[jega->egapal[attr & 0x0f]]; - bg = jega->pallook[jega->egapal[attr >> 4]]; + fg = jega->pallook[jega->egapal[attr & 0x0f] & mask]; + bg = jega->pallook[jega->egapal[attr >> 4] & mask]; if ((attr & 0x80) && attrblink) { - bg = jega->pallook[jega->egapal[(attr >> 4) & 7]]; + bg = jega->pallook[jega->egapal[(attr >> 4) & 7] & mask]; if (blinked) fg = bg; } @@ -325,32 +384,35 @@ jega_render_text(void *priv) // charaddr ^= 0x100; charaddr *= 19; - uint32_t dat = jega->jfont_sbcs_19[charaddr + jega->ega.sc]; + uint32_t dat = jega->jfont_sbcs_19[charaddr + *sc]; for (int xx = 0; xx < charwidth; xx++) p[xx] = (dat & (0x80 >> xx)) ? fg : bg; if (attr_basic & 0x20) { /* vertical line */ p[0] = fg; } - if ((jega->ega.sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ + if ((*sc == jega->regs[RPULP]) && (attr_basic & 0x10)) { /* underline */ for (int xx = 0; xx < charwidth; xx++) p[xx] = fg; } p += charwidth; } } - jega->ega.ma += 4; + *ma += 4; } - jega->ega.ma &= 0x3ffff; + *ma &= 0x3ffff; } } static void jega_out(uint16_t addr, uint8_t val, void *priv) { - jega_t *jega = (jega_t *) priv; - uint16_t chr; + jega_t *jega = (jega_t *) priv; + uint8_t pal4to16[16] = { 0, 7, 0x38, 0x3f, 0, 3, 4, 0x3f, 0, 2, 4, 0x3e, 0, 3, 5, 0x3f }; + uint16_t chr; + // jega_log("JEGA Out %04X %02X(%d) %04X:%04X\n", addr, val, val, cs >> 4, cpu_state.pc); + switch (addr) { case 0x3c0: case 0x3c1: @@ -367,9 +429,19 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega->attrregs[jega->attraddr & 31] = val; if (jega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { + if (!jega->is_vga) jega->egapal[c] = jega->attrregs[c] & 0x3f; + else if (jega->attrregs[0x10] & 0x80) + jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); + else if (jega->vga.svga.ati_4color) + jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else + jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); } - jega->ega.fullchange = changeframecount; + if (jega->is_vga) + jega->vga.svga.fullchange = changeframecount; + else + jega->ega.fullchange = changeframecount; } } jega->attrff ^= 1; @@ -395,12 +467,17 @@ jega_out(uint16_t addr, uint8_t val, void *priv) switch (jega->regs_index) { case RMOD1: /* if the value is changed */ - // if (jega->regs[jega->regs_index] != val) { - if (val & 0x40) - jega->ega.render_override = NULL; - else - jega->ega.render_override = jega_render_text; - // } + if (jega->is_vga) { + if (val & 0x40) + jega->vga.svga.render_override = NULL; + else + jega->vga.svga.render_override = jega_render_text; + } else { + if (val & 0x40) + jega->ega.render_override = NULL; + else + jega->ega.render_override = jega_render_text; + } break; case RDAGS: switch (val & 0x03) { @@ -470,8 +547,14 @@ jega_out(uint16_t addr, uint8_t val, void *priv) default: break; } - if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ - ega_out(addr, val, &jega->ega); + + /* Accessing to Slave EGA is redirected to Master in AX-1. */ + if (jega->regs[RMOD1] & 0x0c) { + if (jega->is_vga) + vga_out(addr, val, &jega->vga); + else + ega_out(addr, val, &jega->ega); + } } static uint8_t @@ -480,6 +563,7 @@ jega_in(uint16_t addr, void *priv) jega_t *jega = (jega_t *) priv; uint8_t ret = INVALIDACCESS8; uint16_t chr; + switch (addr) { case 0x3b5: case 0x3d5: @@ -515,8 +599,13 @@ jega_in(uint16_t addr, void *priv) case 0x3da: jega->attrff = 0; default: - if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave is redirected to Master in AX-1. */ - ret = ega_in(addr, &jega->ega); + /* Accessing to Slave is redirected to Master in AX-1. */ + if (jega->regs[RMOD1] & 0x0c) { + if (jega->is_vga) + ret = vga_in(addr, &jega->vga); + else + ret = ega_in(addr, &jega->ega); + } break; } // jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); @@ -619,19 +708,29 @@ LoadFontxFile(const char *fn, void *priv) } static void -jega_commoninit(void *priv) +jega_commoninit(const device_t *info, void *priv, int vga) { jega_t *jega = (jega_t *) priv; - for (int c = 0; c < 256; c++) { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + jega->is_vga = vga; + if (vga) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); + vga_init(info, &jega->vga, 1); + jega->vga.svga.priv_parent = jega; + jega->pallook = jega->vga.svga.pallook; + } else { + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + jega->pallook = pallook64; + ega_init(&jega->ega, 9, 0); + ega_set_type(&jega->ega, EGA_SUPEREGA); + jega->ega.priv_parent = jega; + mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, + ega_read, NULL, NULL, ega_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, &jega->ega); } - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); - jega->pallook = pallook64; - ega_init(&jega->ega, 9, 0); - ega_set_type(&jega->ega, EGA_SUPEREGA); - jega->ega.priv_parent = jega; - mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); /* I/O 3DD and 3DE are used by Oki if386 */ io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); jega->regs[RMOD1] = 0x48; @@ -646,7 +745,21 @@ jega_standalone_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - jega_commoninit(jega); + jega_commoninit(info, jega, 0); + + return jega; +} + +static void * +jvga_standalone_init(const device_t *info) +{ + jega_t *jega = calloc(1, sizeof(jega_t)); + + rom_init(&jega->bios_rom, JVGA_PATH_BIOS, 0xc0000, 0x8000, 0x7fff, 0, 0); + memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); + LoadFontxFile(JVGA_PATH_FONTDBCS, jega); + + jega_commoninit(info, jega, 1); return jega; } @@ -693,9 +806,15 @@ jega_close(void *priv) } pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif - if (jega->ega.eeprom) - free(jega->ega.eeprom); - free(jega->ega.vram); + + if (jega->is_vga) + svga_close(&jega->vga.svga); + else { + if (jega->ega.eeprom) + free(jega->ega.eeprom); + free(jega->ega.vram); + } + free(jega); } @@ -703,8 +822,13 @@ static void jega_recalctimings(void *priv) { jega_t *jega = (jega_t *) priv; - ega_recalctimings(&jega->ega); + + if (jega->is_vga) + svga_recalctimings(&jega->vga.svga); + else + ega_recalctimings(&jega->ega); } + static void jega_speed_changed(void *priv) { @@ -733,6 +857,20 @@ const device_t jega_device = { .config = NULL }; +const device_t jvga_device = { + .name = "OKIVGA/H-2 (JVGA/H)", + .internal_name = "jvga", + .flags = DEVICE_ISA, + .local = 0, + .init = jvga_standalone_init, + .close = jega_close, + .reset = NULL, + .available = jega_standalone_available, + .speed_changed = jega_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + static uint8_t p65idx = 0; // static uint8_t p3de_idx = 0; static uint8_t p65[6]; @@ -834,7 +972,7 @@ if386jega_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - jega_commoninit(jega); + jega_commoninit(info, jega, 0); io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 1fd2460bd..c7a65120f 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1174,7 +1174,10 @@ svga_do_render(svga_t *svga) } if (!svga->override) { - svga->render(svga); + if (svga->render_override) + svga->render_override(svga->priv_parent); + else + svga->render(svga); svga->x_add = (svga->monitor->mon_overscan_x >> 1); svga_render_overscan_left(svga); diff --git a/src/video/vid_table.c b/src/video/vid_table.c index be26d9e18..b90d7c3e4 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -96,6 +96,7 @@ video_cards[] = { { .device = &genius_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &nga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &ogc_device, .flags = VIDEO_FLAG_TYPE_NONE }, + { .device = &jvga_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti037c_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti067_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &oti077_device, .flags = VIDEO_FLAG_TYPE_NONE }, diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 97889e007..0a0fbd8e1 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -31,7 +31,8 @@ #include <86box/vid_svga.h> #include <86box/vid_vga.h> -static video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; +video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; + static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; @@ -135,8 +136,23 @@ int vga_isenabled(void* p) return svga->vga_enabled; } +void +vga_init(const device_t *info, vga_t *vga, int enabled) +{ + svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ + NULL, + vga_in, vga_out, + NULL, + NULL); + + vga->svga.bpp = 8; + vga->svga.miscout = 1; + + vga->svga.vga_enabled = enabled; +} + static void * -vga_init(const device_t *info) +vga_standalone_init(const device_t *info) { vga_t *vga = malloc(sizeof(vga_t)); memset(vga, 0, sizeof(vga_t)); @@ -145,16 +161,7 @@ vga_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); - - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - - vga->svga.bpp = 8; - vga->svga.miscout = 1; + vga_init(info, vga, 0); return vga; } @@ -171,17 +178,7 @@ ps1vga_init(const device_t *info) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa); - svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); - - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - - vga->svga.bpp = 8; - vga->svga.miscout = 1; - vga->svga.vga_enabled = 1; + vga_init(info, vga, 1); return vga; } @@ -223,7 +220,7 @@ const device_t vga_device = { .internal_name = "vga", .flags = DEVICE_ISA, .local = 0, - .init = vga_init, + .init = vga_standalone_init, .close = vga_close, .reset = NULL, .available = vga_available, From 47febdf1969b5532ee6be6c321b802e5ff19fd02 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:42:11 +0100 Subject: [PATCH 144/158] JVGA: Read CRTC registers from VGA rather than EGA, fixes Wolfenstein 3D. --- src/video/vid_jega.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index af20444dd..745c76e24 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -29,6 +29,7 @@ #include <86box/pic.h> #include <86box/pit.h> #include <86box/plat.h> +#include <86box/plat_fallthrough.h> #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> @@ -592,12 +593,18 @@ jega_in(uint16_t addr, void *priv) break; } jega_log("JEGA In %04X(%02X) %02X %04X:%04X\n", addr, jega->regs_index, ret, cs >> 4, cpu_state.pc); - } else if (jega->regs[RMOD1] & 0x0C) /* Accessing to Slave EGA is redirected to Master in AX-1. */ - ret = ega_in(addr, &jega->ega); + } else if (jega->regs[RMOD1] & 0x0c) { + /* Accessing to Slave EGA is redirected to Master in AX-1. */ + if (jega->is_vga) + ret = vga_in(addr, &jega->vga); + else + ret = ega_in(addr, &jega->ega); + } break; case 0x3ba: case 0x3da: jega->attrff = 0; + fallthrough; default: /* Accessing to Slave is redirected to Master in AX-1. */ if (jega->regs[RMOD1] & 0x0c) { From 8f6f21b57e14b370a7e8cae4cb5930d2efe6ea11 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 06:54:45 +0100 Subject: [PATCH 145/158] IBM VGA: Re-add the forgotten (S)VGA I/O handlers. --- src/video/vid_vga.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 0a0fbd8e1..8289fd4cb 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -154,8 +154,7 @@ vga_init(const device_t *info, vga_t *vga, int enabled) static void * vga_standalone_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *vga = calloc(1, sizeof(vga_t)); rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); @@ -163,6 +162,8 @@ vga_standalone_init(const device_t *info) vga_init(info, vga, 0); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + return vga; } @@ -170,8 +171,7 @@ vga_standalone_init(const device_t *info) void * ps1vga_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *vga = calloc(1, sizeof(vga_t)); if (info->flags & DEVICE_MCA) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca); @@ -180,6 +180,8 @@ ps1vga_init(const device_t *info) vga_init(info, vga, 1); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + return vga; } From 6366ff758082d16430bbbf5e81d9845ba8270985 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 28 Mar 2025 08:09:51 +0100 Subject: [PATCH 146/158] JEGA: Fix two uninitialized variables. --- src/video/vid_jega.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 745c76e24..3d1cfe476 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -250,9 +250,9 @@ jega_render_text(void *priv) int sc_wide = *sc - jega->start_scan_count; const bool cursoron = (blinked || jega->cursorblink_disable) && (*sc >= jega->regs[RCCSL]) && (*sc <= jega->regs[RCCEL]); + uint32_t attr_basic = 0; uint32_t chr_first; - uint32_t attr_basic; - int fg; + int fg = 0; int bg; for (int x = 0; x < (*hdisp + *scrollcache); x += charwidth) { From 94cf5d59a2b919cfb5e916e8d715708ff138f54e Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 28 Mar 2025 22:35:56 +0600 Subject: [PATCH 147/158] host_x86_MOV8_REG_ABS: Avoid more fatals --- src/codegen_new/codegen_backend_x86-64_ops.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codegen_new/codegen_backend_x86-64_ops.c b/src/codegen_new/codegen_backend_x86-64_ops.c index c70112c86..fc6c1b492 100644 --- a/src/codegen_new/codegen_backend_x86-64_ops.c +++ b/src/codegen_new/codegen_backend_x86-64_ops.c @@ -723,7 +723,11 @@ host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p) codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/ codegen_addlong(block, ram_offset); } else { - fatal("host_x86_MOV8_REG_ABS - out of range\n"); + codegen_alloc_bytes(block, 10); + codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/ + codegen_addquad(block, (uintptr_t) p); + codegen_alloc_bytes(block, 3); + codegen_addbyte3(block, 0x41, 0x8a, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/ } } void From dd0e6261337df4384df3bb94ffe691bcd67307be Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 29 Mar 2025 01:18:37 +0600 Subject: [PATCH 148/158] Set LC_NUMERIC to "C" in program startup For whatever fucking reason, glibc's functions dealing with decimal numbers apparently can only accept either commas or dots in strings, but not both. Meanwhile, both Windows and macOS have no apparent issues accepting both. I will never understand why they decided to even consider such behaviour acceptable, especially since those ARE used for parsing decimal numbers in many programs, but I guess it's their own version of Not Invented Here syndrome that they (or anyone else) can't be bothered to deal with. This is not how good C standard libraries are written, at all. --- src/qt/qt_main.cpp | 3 +++ src/utils/ini.c | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 2e0ce33e0..2ef797bd1 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -94,6 +94,8 @@ extern int qt_nvr_save(void); bool cpu_thread_running = false; } +#include + void qt_set_sequence_auto_mnemonic(bool b); #ifdef Q_OS_WINDOWS @@ -525,6 +527,7 @@ main(int argc, char *argv[]) QApplication app(argc, argv); QLocale::setDefault(QLocale::C); + setlocale(LC_NUMERIC, "C"); #ifdef Q_OS_WINDOWS Q_INIT_RESOURCE(darkstyle); diff --git a/src/utils/ini.c b/src/utils/ini.c index f5dfdef46..e23f83670 100644 --- a/src/utils/ini.c +++ b/src/utils/ini.c @@ -756,8 +756,9 @@ double ini_section_get_double(ini_section_t self, const char *name, double def) { section_t *section = (section_t *) self; - const entry_t *entry; - double value = 0; + entry_t *entry; + double value = 0; + int res = 0; if (section == NULL) return def; @@ -766,7 +767,17 @@ ini_section_get_double(ini_section_t self, const char *name, double def) if (entry == NULL) return def; - sscanf(entry->data, "%lg", &value); + res = sscanf(entry->data, "%lg", &value); + if (res == EOF || res <= 0) { + int i = 0; + for (i = 0; i < strlen(entry->data); i++) { + if (entry->data[i] == ',') { + entry->data[i] = '.'; + entry->wdata[i] = L'.'; + } + } + (void)sscanf(entry->data, "%lg", &value); + } return value; } From f422a9ce3dc14edf75b6c12d793c829a82db3f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:11:26 +0100 Subject: [PATCH 149/158] qt: implement authentic icon grayscaling --- src/qt/qt_styleoverride.cpp | 40 +++++++++++++++++++++++++++++++++++++ src/qt/qt_styleoverride.hpp | 4 ++++ 2 files changed, 44 insertions(+) diff --git a/src/qt/qt_styleoverride.cpp b/src/qt/qt_styleoverride.cpp index 60a7162a5..0bade8fa6 100644 --- a/src/qt/qt_styleoverride.cpp +++ b/src/qt/qt_styleoverride.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #ifdef Q_OS_WINDOWS #include @@ -66,3 +69,40 @@ StyleOverride::polish(QWidget *widget) qobject_cast(widget)->view()->setMinimumWidth(widget->minimumSizeHint().width()); } } + +QPixmap +StyleOverride::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const +{ + if (iconMode != QIcon::Disabled) { + return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); + } + + auto image = pixmap.toImage(); + + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + // checkerboard transparency + if (((x ^ y) & 1) == 0) { + image.setPixelColor(x, y, Qt::transparent); + continue; + } + + auto color = image.pixelColor(x, y); + + // convert to grayscale using the NTSC formula + auto avg = 0.0; + avg += color.blueF() * 0.114; + avg += color.greenF() * 0.587; + avg += color.redF() * 0.299; + + color.setRedF(avg); + color.setGreenF(avg); + color.setBlueF(avg); + + image.setPixelColor(x, y, color); + + } + } + + return QPixmap::fromImage(image); +} diff --git a/src/qt/qt_styleoverride.hpp b/src/qt/qt_styleoverride.hpp index c04d01a12..840aa6ad6 100644 --- a/src/qt/qt_styleoverride.hpp +++ b/src/qt/qt_styleoverride.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include class StyleOverride : public QProxyStyle { public: @@ -14,6 +17,7 @@ public: QStyleHintReturn *returnData = nullptr) const override; void polish(QWidget *widget) override; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const override; }; #endif From c00c432398dd2d1a7f0c2bfe20a5f9756867e894 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 00:10:39 +0100 Subject: [PATCH 150/158] EGA: Fix colors in mono mode and attribute registers, fixes #5395. --- src/video/vid_ega.c | 11 +++++++---- src/video/vid_ega_render.c | 10 +++++++--- src/video/vid_jega.c | 15 ++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 17b3fb593..f002ef999 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -112,10 +112,13 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->fullchange = changeframecount; if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { - if (ega->attrregs[0x10] & 0x80) - ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); - else - ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + if (ega->chipset) { + if (ega->attrregs[0x10] & 0x80) + ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); + else + ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); + } else + ega->egapal[c] = ega->attrregs[c] & 0x3f; } ega->fullchange = changeframecount; } diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 261474742..10667084a 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -172,15 +172,19 @@ ega_render_text(ega_t *ega) uint32_t dat = ega->vram[charaddr + (ega->sc << 2)]; dat <<= 1; - if ((chr & ~0x1F) == 0xC0 && attrlinechars) + if (((chr & ~0x1f) == 0xc0) && attrlinechars) dat |= (dat >> 1) & 1; for (int xx = 0; xx < charwidth; xx++) { if (monoattrs) { + int bit = (dat & (0x100 >> (xx >> dwshift))) ? 1 : 0; + int blink = (!drawcursor && (attr & 0x80) && attrblink && blinked); if ((ega->sc == ega->crtc[0x14]) && ((attr & 7) == 1)) - p[xx] = ega->mdacols[attr][attrblink][1]; + p[xx] = ega->mdacols[attr][blink][1]; else - p[xx] = ega->mdacols[attr][attrblink][dat & (0x100 >> (xx >> dwshift))]; + p[xx] = ega->mdacols[attr][blink][bit]; + if (drawcursor) + p[xx] ^= ega->mdacols[attr][0][1]; p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]]; } else p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg; diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 3d1cfe476..11c9cbf8d 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -430,14 +430,15 @@ jega_out(uint16_t addr, uint8_t val, void *priv) jega->attrregs[jega->attraddr & 31] = val; if (jega->attraddr < 0x10) { for (uint8_t c = 0; c < 16; c++) { - if (!jega->is_vga) + if (jega->is_vga) { + if (jega->attrregs[0x10] & 0x80) + jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); + else if (jega->vga.svga.ati_4color) + jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; + else + jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); + } else jega->egapal[c] = jega->attrregs[c] & 0x3f; - else if (jega->attrregs[0x10] & 0x80) - jega->egapal[c] = (jega->attrregs[c] & 0xf) | ((jega->attrregs[0x14] & 0xf) << 4); - else if (jega->vga.svga.ati_4color) - jega->egapal[c] = pal4to16[(c & 0x03) | ((val >> 2) & 0xc)]; - else - jega->egapal[c] = (jega->attrregs[c] & 0x3f) | ((jega->attrregs[0x14] & 0xc) << 4); } if (jega->is_vga) jega->vga.svga.fullchange = changeframecount; From ed4a312f4f6dec174a848dfa13bee8d9cc551976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Fri, 28 Mar 2025 23:13:23 +0100 Subject: [PATCH 151/158] Remove support for icon sets --- src/config.c | 11 ----- src/include/86box/86box.h | 1 - src/qt/qt.c | 2 - src/qt/qt_machinestatus.cpp | 44 ++++++++--------- src/qt/qt_mediamenu.cpp | 18 +++---- src/qt/qt_progsettings.cpp | 62 ------------------------ src/qt/qt_progsettings.hpp | 3 -- src/qt/qt_progsettings.ui | 72 ++++++---------------------- src/qt/qt_settings.cpp | 2 +- src/qt/qt_settingsfloppycdrom.cpp | 10 ++-- src/qt/qt_settingsharddisks.cpp | 2 +- src/qt/qt_settingsotherremovable.cpp | 8 ++-- src/unix/unix.c | 1 - 13 files changed, 57 insertions(+), 179 deletions(-) diff --git a/src/config.c b/src/config.c index 2e6a5460f..8ff7d548c 100644 --- a/src/config.c +++ b/src/config.c @@ -192,12 +192,6 @@ load_general(void) else if (mouse_sensitivity > 2.0) mouse_sensitivity = 2.0; - p = ini_section_get_string(cat, "iconset", NULL); - if (p != NULL) - strcpy(icon_set, p); - else - strcpy(icon_set, ""); - enable_discord = !!ini_section_get_int(cat, "enable_discord", 0); open_dir_usr_path = ini_section_get_int(cat, "open_dir_usr_path", 0); @@ -2038,11 +2032,6 @@ save_general(void) ini_section_set_string(cat, "language", buffer); } - if (!strcmp(icon_set, "")) - ini_section_delete_var(cat, "iconset"); - else - ini_section_set_string(cat, "iconset", icon_set); - if (enable_discord) ini_section_set_int(cat, "enable_discord", enable_discord); else diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index c58d595c5..61de69cf3 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -118,7 +118,6 @@ extern int vid_resize; /* (C) allow resizing */ extern int invert_display; /* (C) invert the display */ extern int suppress_overscan; /* (C) suppress overscans */ extern uint32_t lang_id; /* (C) language code identifier */ -extern char icon_set[256]; /* (C) iconset identifier */ extern int scale; /* (C) screen scale factor */ extern int dpi_scale; /* (C) DPI scaling of the emulated screen */ extern int vid_api; /* (C) video renderer */ diff --git a/src/qt/qt.c b/src/qt/qt.c index a9a6460eb..ecf4b964b 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -35,8 +35,6 @@ qt_nvr_save(void) return nvr_save(); } -char icon_set[256] = ""; /* name of the iconset to be used */ - int plat_vidapi(const char *api) { diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index a00cc032b..eff29a232 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -176,24 +176,24 @@ static const QString pixmap_empty_active = QStringLiteral("_empty_active"); void PixmapSetEmpty::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); } void PixmapSetActive::load(const QString &basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); } void PixmapSetEmptyActive::load(QString basePath) { - normal = ProgSettings::loadIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = ProgSettings::loadIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - empty = ProgSettings::loadIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); - empty_active = ProgSettings::loadIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); + normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); + active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + empty_active = QIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); } } @@ -202,21 +202,21 @@ struct MachineStatus::States { States(QObject *parent) { - pixmaps.cartridge.load("/cartridge%1.ico"); - pixmaps.cassette.load("/cassette%1.ico"); - pixmaps.floppy_disabled.normal = ProgSettings::loadIcon(QStringLiteral("/floppy_disabled.ico")).pixmap(pixmap_size); + pixmaps.cartridge.load(":/settings/qt/icons/cartridge%1.ico"); + pixmaps.cassette.load(":/settings/qt/icons/cassette%1.ico"); + pixmaps.floppy_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size); pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; - pixmaps.floppy_525.load("/floppy_525%1.ico"); - pixmaps.floppy_35.load("/floppy_35%1.ico"); - pixmaps.cdrom.load("/cdrom%1.ico"); - pixmaps.zip.load("/zip%1.ico"); - pixmaps.mo.load("/mo%1.ico"); - pixmaps.hd.load("/hard_disk%1.ico"); - pixmaps.net.load("/network%1.ico"); - pixmaps.sound = ProgSettings::loadIcon("/sound.ico").pixmap(pixmap_size); - pixmaps.soundMuted = ProgSettings::loadIcon("/sound_mute.ico").pixmap(pixmap_size); + pixmaps.floppy_525.load(":/settings/qt/icons/floppy_525%1.ico"); + pixmaps.floppy_35.load(":/settings/qt/icons/floppy_35%1.ico"); + pixmaps.cdrom.load(":/settings/qt/icons/cdrom%1.ico"); + pixmaps.zip.load(":/settings/qt/icons/zip%1.ico"); + pixmaps.mo.load(":/settings/qt/icons/mo%1.ico"); + pixmaps.hd.load(":/settings/qt/icons/hard_disk%1.ico"); + pixmaps.net.load(":/settings/qt/icons/network%1.ico"); + pixmaps.sound = QIcon(":/settings/qt/icons/sound.ico").pixmap(pixmap_size); + pixmaps.soundMuted = QIcon(":/settings/qt/icons/sound_mute.ico").pixmap(pixmap_size); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -511,7 +511,7 @@ MachineStatus::refresh(QStatusBar *sbar) config_save(); if (d->sound) d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); - + muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); }); } @@ -697,7 +697,7 @@ MachineStatus::refresh(QStatusBar *sbar) d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); if (muteUnmuteAction) muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); - + connect(d->sound.get(), &ClickableLabel::clicked, this, [this](QPoint pos) { this->soundMenu->popup(pos - QPoint(0, this->soundMenu->sizeHint().height())); }); diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index fdea16c2a..f7abebdf1 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -154,10 +154,10 @@ MediaMenu::refresh(QMenu *parentMenu) MachineStatus::iterateCDROM([this, parentMenu](int i) { auto *menu = parentMenu->addMenu(""); cdromMutePos = menu->children().count(); - menu->addAction(ProgSettings::loadIcon("/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); menu->addSeparator(); - menu->addAction(ProgSettings::loadIcon("/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); - menu->addAction(ProgSettings::loadIcon("/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cdromImageHistoryPos[slot] = menu->children().count(); @@ -170,7 +170,7 @@ MediaMenu::refresh(QMenu *parentMenu) for (const auto &letter : driveLetters) { auto drive = QString("%1:\\").arg(letter); if (GetDriveType(drive.toUtf8().constData()) == DRIVE_CDROM) - menu->addAction(ProgSettings::loadIcon("/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); + menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); } menu->addSeparator(); #endif // Q_OS_WINDOWS @@ -666,7 +666,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cdromImageHistoryPos[slot]]); if (fn.left(8) == "ioctl://") { - menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); + menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico"); #ifdef Q_OS_WINDOWS menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(2)).toUtf8().constData(); #else @@ -674,7 +674,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) #endif } else { fi.setFile(fn); - menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); + menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); menu_item_name = fn.isEmpty() ? tr("previous image").toUtf8().constData() : fn.toUtf8().constData(); } imageHistoryUpdatePos->setIcon(menu_icon); @@ -727,7 +727,7 @@ MediaMenu::cdromUpdateMenu(int i) auto childs = menu->children(); auto *muteMenu = dynamic_cast(childs[cdromMutePos]); - muteMenu->setIcon(ProgSettings::loadIcon((cdrom[i].sound_on == 0) ? "/cdrom_unmute.ico" : "/cdrom_mute.ico")); + muteMenu->setIcon(QIcon((cdrom[i].sound_on == 0) ? ":/settings/qt/icons/cdrom_unmute.ico" : ":/settings/qt/icons/cdrom_mute.ico")); muteMenu->setText((cdrom[i].sound_on == 0) ? tr("&Unmute") : tr("&Mute")); auto *imageMenu = dynamic_cast(childs[cdromImagePos]); @@ -740,13 +740,13 @@ MediaMenu::cdromUpdateMenu(int i) menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(name.length() - 8)); #endif name2 = menu_item_name; - menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); + menu_icon = QIcon(":/settings/qt/icons/cdrom_host.ico"); } else { QFileInfo fi(cdrom[i].image_path); menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : name.toUtf8().constData(); name2 = name; - menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); + menu_icon = fi.isDir() ? QIcon(":/settings/qt/icons/cdrom_folder.ico") : QIcon(":/settings/qt/icons/cdrom_image.ico"); } imageMenu->setIcon(menu_icon); imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData())); diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index ce6c21dd6..2fd108186 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -36,71 +36,16 @@ extern "C" { #include <86box/rom.h> } -static QMap iconset_to_qt; extern MainWindow *main_window; ProgSettings::CustomTranslator *ProgSettings::translator = nullptr; QTranslator *ProgSettings::qtTranslator = nullptr; -QString -ProgSettings::getIconSetPath() -{ - if (iconset_to_qt.isEmpty()) { - // Always include default bundled icons - iconset_to_qt.insert("", ":/settings/qt/icons"); - // Walk rom_paths to get the candidates - for (rom_path_t *emu_rom_path = &rom_paths; emu_rom_path != nullptr; emu_rom_path = emu_rom_path->next) { - // Check for icons subdir in each candidate - QDir roms_icons_dir(QString(emu_rom_path->path) + "/icons"); - if (roms_icons_dir.isReadable()) { - auto dirList = roms_icons_dir.entryList(QDir::AllDirs | QDir::Executable | QDir::Readable); - for (auto &curIconSet : dirList) { - if (curIconSet == "." || curIconSet == "..") { - continue; - } - iconset_to_qt.insert(curIconSet, (roms_icons_dir.canonicalPath() + '/') + curIconSet); - } - } - } - } - return iconset_to_qt[icon_set]; -} - -QIcon -ProgSettings::loadIcon(QString file) -{ - (void) getIconSetPath(); - if (!QFile::exists(iconset_to_qt[icon_set] + file)) - return QIcon(iconset_to_qt[""] + file); - return QIcon(iconset_to_qt[icon_set] + file); -} ProgSettings::ProgSettings(QWidget *parent) : QDialog(parent) , ui(new Ui::ProgSettings) { ui->setupUi(this); - (void) getIconSetPath(); - ui->comboBox->setItemData(0, ""); - ui->comboBox->setCurrentIndex(0); - for (auto i = iconset_to_qt.begin(); i != iconset_to_qt.end(); i++) { - if (i.key() == "") - continue; - QFile iconfile(i.value() + "/iconinfo.txt"); - iconfile.open(QFile::ReadOnly); - QString friendlyName; - QString iconsetinfo(iconfile.readAll()); - iconfile.close(); - if (iconsetinfo.isEmpty()) - friendlyName = i.key(); - else - friendlyName = iconsetinfo.split('\n')[0]; - ui->comboBox->addItem(friendlyName, i.key()); - if (strcmp(icon_set, i.key().toUtf8().data()) == 0) { - ui->comboBox->setCurrentIndex(ui->comboBox->findData(i.key())); - } - } - ui->comboBox->setItemData(0, '(' + tr("Default") + ')', Qt::DisplayRole); - ui->comboBoxLanguage->setItemData(0, 0xFFFF); for (auto i = lcid_langcode.begin(); i != lcid_langcode.end(); i++) { if (i.key() == 0xFFFF) @@ -129,7 +74,6 @@ ProgSettings::ProgSettings(QWidget *parent) void ProgSettings::accept() { - strcpy(icon_set, ui->comboBox->currentData().toString().toUtf8().data()); lang_id = ui->comboBoxLanguage->currentData().toUInt(); open_dir_usr_path = ui->openDirUsrPath->isChecked() ? 1 : 0; confirm_exit = ui->checkBoxConfirmExit->isChecked() ? 1 : 0; @@ -161,12 +105,6 @@ ProgSettings::~ProgSettings() delete ui; } -void -ProgSettings::on_pushButton_released() -{ - ui->comboBox->setCurrentIndex(0); -} - #ifdef Q_OS_WINDOWS /* Return the standard font name on Windows, which is overridden per-language to prevent CJK fonts with embedded bitmaps being chosen as a fallback. */ diff --git a/src/qt/qt_progsettings.hpp b/src/qt/qt_progsettings.hpp index 642b2002d..b4e59e02d 100644 --- a/src/qt/qt_progsettings.hpp +++ b/src/qt/qt_progsettings.hpp @@ -14,8 +14,6 @@ class ProgSettings : public QDialog { public: explicit ProgSettings(QWidget *parent = nullptr); ~ProgSettings(); - static QString getIconSetPath(); - static QIcon loadIcon(QString file); #ifdef Q_OS_WINDOWS static QString getFontName(uint32_t lcid); #endif @@ -56,7 +54,6 @@ public: protected slots: void accept() override; private slots: - void on_pushButton_released(); void on_pushButtonLanguage_released(); void on_horizontalSlider_valueChanged(int value); diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index f7b32ce84..d3ebf8c85 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -29,21 +29,14 @@ QLayout::SizeConstraint::SetFixedSize - + Default - - - - Icon set: - - - - + Qt::Orientation::Horizontal @@ -56,7 +49,7 @@ - + 30 @@ -68,7 +61,7 @@ - + <html><head/><body><p>When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.</p></body></html> @@ -78,14 +71,7 @@ - - - - Default - - - - + Qt::Orientation::Horizontal @@ -98,14 +84,14 @@ - + Default - + 10 @@ -127,21 +113,21 @@ - + Language: - + Ask for confirmation before saving settings - + Qt::Orientation::Horizontal @@ -151,63 +137,35 @@ - + Inhibit multimedia keys on Windows - - - - false - - - 30 - - - - (Default) - - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - + Mouse sensitivity: - + Ask for confirmation before hard resetting - + Ask for confirmation before quitting - + Display hotkey message when entering full-screen mode diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 471558e22..19a537652 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -95,7 +95,7 @@ SettingsModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: return tr(pages.at(index.row()).toUtf8().data()); case Qt::DecorationRole: - return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()])); + return QIcon(QString(":/settings/qt/icons/%1.ico").arg(page_icons[index.row()])); case Qt::SizeHintRole: return QSize(-1, fontHeight * 2); default: diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index cc58d3cde..52d737ae6 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -46,11 +46,11 @@ setFloppyType(QAbstractItemModel *model, const QModelIndex &idx, int type) { QIcon icon; if (type == 0) - icon = ProgSettings::loadIcon("/floppy_disabled.ico"); + icon = QIcon(":/settings/qt/icons/floppy_disabled.ico"); else if (type >= 1 && type <= 6) - icon = ProgSettings::loadIcon("/floppy_525.ico"); + icon = QIcon(":/settings/qt/icons/floppy_525.ico"); else - icon = ProgSettings::loadIcon("/floppy_35.ico"); + icon = QIcon(":/settings/qt/icons/floppy_35.ico"); model->setData(idx, QObject::tr(fdd_getname(type))); model->setData(idx, type, Qt::UserRole); @@ -64,12 +64,12 @@ setCDROMBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint switch (bus) { case CDROM_BUS_DISABLED: - icon = ProgSettings::loadIcon("/cdrom_disabled.ico"); + icon = QIcon(":/settings/qt/icons/cdrom_disabled.ico"); break; case CDROM_BUS_ATAPI: case CDROM_BUS_SCSI: case CDROM_BUS_MITSUMI: - icon = ProgSettings::loadIcon("/cdrom.ico"); + icon = QIcon(":/settings/qt/icons/cdrom.ico"); break; } diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index e679dafa5..ded50ac34 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -81,7 +81,7 @@ addRow(QAbstractItemModel *model, hard_disk_t *hd) QString busName = Harddrives::BusChannelName(hd->bus_type, hd->channel); model->setData(model->index(row, ColumnBus), busName); - model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon("/hard_disk.ico"), Qt::DecorationRole); + model->setData(model->index(row, ColumnBus), QIcon(":/settings/qt/icons/hard_disk.ico"), Qt::DecorationRole); model->setData(model->index(row, ColumnBus), hd->bus_type, DataBus); model->setData(model->index(row, ColumnBus), hd->bus_type, DataBusPrevious); model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel); diff --git a/src/qt/qt_settingsotherremovable.cpp b/src/qt/qt_settingsotherremovable.cpp index 1a6dceacb..8a810a4fb 100644 --- a/src/qt/qt_settingsotherremovable.cpp +++ b/src/qt/qt_settingsotherremovable.cpp @@ -46,11 +46,11 @@ setMOBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_t QIcon icon; switch (bus) { case MO_BUS_DISABLED: - icon = ProgSettings::loadIcon("/mo_disabled.ico"); + icon = QIcon(":/settings/qt/icons/mo_disabled.ico"); break; case MO_BUS_ATAPI: case MO_BUS_SCSI: - icon = ProgSettings::loadIcon("/mo.ico"); + icon = QIcon(":/settings/qt/icons/mo.ico"); break; default: @@ -81,11 +81,11 @@ setZIPBus(QAbstractItemModel *model, const QModelIndex &idx, uint8_t bus, uint8_ QIcon icon; switch (bus) { case ZIP_BUS_DISABLED: - icon = ProgSettings::loadIcon("/zip_disabled.ico"); + icon = QIcon(":/settings/qt/icons/zip_disabled.ico"); break; case ZIP_BUS_ATAPI: case ZIP_BUS_SCSI: - icon = ProgSettings::loadIcon("/zip.ico"); + icon = QIcon(":/settings/qt/icons/zip.ico"); break; default: diff --git a/src/unix/unix.c b/src/unix/unix.c index 81312d25d..c41aee2a4 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -73,7 +73,6 @@ static int exit_event = 0; static int fullscreen_pending = 0; uint32_t lang_id = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US uint32_t lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US -char icon_set[256] = ""; /* name of the iconset to be used */ static const uint16_t sdl_to_xt[0x200] = { [SDL_SCANCODE_ESCAPE] = 0x01, From 8b72c84c028effa55f4751f25da0c51ec1603ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hrdli=C4=8Dka?= <13226155+dhrdlicka@users.noreply.github.com> Date: Sat, 29 Mar 2025 00:13:10 +0100 Subject: [PATCH 152/158] Use indicator overlays for status bar icons --- src/qt/CMakeLists.txt | 3 + src/qt/icons/active.ico | Bin 0 -> 9622 bytes src/qt/icons/cartridge_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cassette_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_active.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/cdrom_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/disabled.ico | Bin 0 -> 9622 bytes src/qt/icons/floppy_35_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_35_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_35_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_active.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/floppy_525_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/hard_disk_active.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_active.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/mo_empty_active.ico | Bin 9622 -> 0 bytes src/qt/icons/network_active.ico | Bin 9622 -> 0 bytes src/qt/icons/network_empty.ico | Bin 6950 -> 0 bytes src/qt/icons/sound_mute.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_active.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_empty.ico | Bin 9622 -> 0 bytes src/qt/icons/zip_empty_active.ico | Bin 9622 -> 0 bytes src/qt/qt_iconindicators.cpp | 33 +++++++++++ src/qt/qt_iconindicators.hpp | 15 +++++ src/qt/qt_machinestatus.cpp | 72 +++++++++++++---------- src/qt_resources.qrc | 25 +------- 30 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 src/qt/icons/active.ico delete mode 100644 src/qt/icons/cartridge_empty.ico delete mode 100644 src/qt/icons/cassette_active.ico delete mode 100644 src/qt/icons/cassette_empty.ico delete mode 100644 src/qt/icons/cassette_empty_active.ico delete mode 100644 src/qt/icons/cdrom_active.ico delete mode 100644 src/qt/icons/cdrom_empty.ico delete mode 100644 src/qt/icons/cdrom_empty_active.ico create mode 100644 src/qt/icons/disabled.ico delete mode 100644 src/qt/icons/floppy_35_active.ico delete mode 100644 src/qt/icons/floppy_35_empty.ico delete mode 100644 src/qt/icons/floppy_35_empty_active.ico delete mode 100644 src/qt/icons/floppy_525_active.ico delete mode 100644 src/qt/icons/floppy_525_empty.ico delete mode 100644 src/qt/icons/floppy_525_empty_active.ico delete mode 100644 src/qt/icons/hard_disk_active.ico delete mode 100644 src/qt/icons/mo_active.ico delete mode 100644 src/qt/icons/mo_empty.ico delete mode 100644 src/qt/icons/mo_empty_active.ico delete mode 100644 src/qt/icons/network_active.ico delete mode 100644 src/qt/icons/network_empty.ico delete mode 100644 src/qt/icons/sound_mute.ico delete mode 100644 src/qt/icons/zip_active.ico delete mode 100644 src/qt/icons/zip_empty.ico delete mode 100644 src/qt/icons/zip_empty_active.ico create mode 100644 src/qt/qt_iconindicators.cpp create mode 100644 src/qt/qt_iconindicators.hpp diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 90ea218af..e6e45fc25 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -194,6 +194,9 @@ add_library(ui STATIC qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui + + qt_iconindicators.hpp + qt_iconindicators.cpp ) if(RTMIDI) diff --git a/src/qt/icons/active.ico b/src/qt/icons/active.ico new file mode 100644 index 0000000000000000000000000000000000000000..9569a3962ba1d76f735492b689bfd8fd1cd95839 GIT binary patch literal 9622 zcmeHMy-ve05Wb2Egc#`1p<6RD@&uPeF)|>`_t`ncazmBG zNh+1Q>f-q4?(8r2-N_Z1$W&%CL0QPdROD7f=JQa0Jr#LD+hP&wkLM!y7a~Ow>d%n- zz}PFu;1wD|I|^ArE|VPOmD{RvvWBd3(9=u@WJr*%e$>-c$D!r9%5n~VAzVwCf3x-L zD9R{no0Wz@1_Ex2&G-&pN6b3g8xZ{r+>Q4)^jD-O_^6&p&v;yRRb8DOJwxFPQg=Io z94Ycf)q5A6rY{dae!UXIbjx<~v$`AjEmPJ$D-8idU^E2W*Ntw;;wX zq|kB=*0^#!Uk1;y%yfFbZ75OD6yxt|l~z9-1B5VuoiJNr4V12GRP zz$>ukVQXGojz^j=#pM{*gT4CrqH`H)9#u@!d@C+>PJP7abOq2&+MD}nFXz$s91dx} zjqM>YF#FB--ZA3Ov)E=2VC+$yKdzrtV(^zA@|%P{Dy%=q^!=pnXdY_Q&#CO|+hnai zwH24O1Fg{zFa!(%L%whyl-?KNnvdAYnk+U;VoXO7gcOl==lnAsd^bt`yvy=sEOrr+3BP(YCsn@n@wlqcC{Kr6(O#` z41Qy}tOtr71OFDWnd2Wni^Zag6@>4(3tsWt>f;tc_>L7Qy)dv3;unM;(|3IQ;1`6i zBJbj#n86bN^oo2f=H!nJi#hpQ9cbcsYybF(q3?e?Z`x{~H*hje-H5tn@#g7`)1@;@gOQEWeM_`sXQZ`seJ}~4lY<$obu~`xy-<(Bkm&Avx zwFSK|@iFHtPVsr0&U>|cfqq)tm-^Ybpljk|Pg}$me6L)=EA>Msg=*kK=gThQqb|AV z7j4_<`Lxz^s=3(-x^qjf(DF@xoLk@ZE}ikvhgyuf$gN9CF6uxRO81@ZyP6>HzzuO( zom?9Iz_7=#@k6JO7)s)2Mx+qmCGjJhvd#K2#&6H!7=6t3kJZHTk8%I-?WFLS_fM)e ztk>)xW?Txfjhr{`gI9WmPAQhm|5Drg5i&=Q oP2FBeH&~kT?`Ox@+M{37fBLp744SNre@%1qcfEd6oPPxV2L@}=i2wiq diff --git a/src/qt/icons/cassette_active.ico b/src/qt/icons/cassette_active.ico deleted file mode 100644 index 32fca20b4bb41aefbd3a03a22c94f0098882b7fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHMJ#*YP5QQe5crq^JLWMi4OqqXRSN_|c0 zTj1fAAViTo>c$_!4Q`3WzV{YO5Q(ZcU5Fpgu9=}oh9_^Gp? zPtIStg#A8Ouz9ZD_n1$K@ip6<;?mgc0)Cz=&tVCUd`Y);jtR@xPyd-z zY1Ep7ab8EAMme7W2)9-rCob=69TzU}=vX!M_1B#A$VCnFBM&~e*@@LLV+vR1r;klI z@oB6%+JYV7_c?g1_-g*%nq2?$3RF?<$Y92lM`KeduRTd90fQc-fk|wf8P^ zI80wPS!U;Gs}`yO?FxNz?Hl@r4gKdJeR?i3KR=dVR`Zk2{SEr!^44og!_QOC#yP)3 z^b40bVcA;#f#wSO&2{A*ERkEjRG&#TK)!houxoF0ovt1?b7?vfXCLst_<<1uUNCV$n1Df84o44e1a z7;`<#2=c+NzjK(Ax_rbaSLI(@KQH~BFKZB2uru`iT8L+EH*rbdV|wcb-o{Q}TrJC3 zzZS!aBU?W&{o?D=nhQ6_`1I!K8|%uo!DT#}4~a+XYidY)fvt0tcF}SAy}1QibMcm& z(=RnXg7z1=e$--a4VT8-wcVlOuKv6RkJ-xkM-ugQdbBaM@7sL^zT*nu1;kVQ0|+l8 XF7Ps9gO>@LlWygDfUo_M0vpc%8S%6om&VLP9htQl#9Hl1E6z8*B{~;xV?QA->Y?@%=w{Y>zF6@F<*w)6-zM2yae8co9N4J8Se$k3;xiw)68wfBPha z*H1%OEE@g2<=t59Gt03vD8~`LouvYtC%wstzS*fdcBS{z}iH7a(?WJ zA=c+&2l0bSr4BJ5F(7u3JoV=oBnHF|Vo&?)cvr2QKg}T~tzYuPXz9bPTfDp7ME&k(!4ZlUy(Bx~l4WSwO|5qJ74;o4DU-zmmMO zJ!+P?0`YpYqp=u|V#N63RDe_c44RJ#t7KNUvDb@grs^cJYG` zwa~$wy^9|tuh8MS{djJ@vUllOj&=pw zXU&%3RC*YDf9LXzXS;9eSiJq-rVFymP8@!EU`JOjG5AV)E)F}W()7Uw(xWeu2U53- zKQUvmi$8p+jh@3?To-?A)FM|rG$($LICKzu%HR8l!4A^X>p2eMMJ*pgE$kl2qZfYc z((zF%r(^f%^Ss}BwET&k3RC_%R zzt-gJi@ADT^C!IGJwh(M(Mw3YdgvUR{82CI)87Bsa<%b;^Z>n`o*s#pJ(q)>+%(5* z0Y7$hxTBK~cK8R+PpurnsgEC?`Piv- z`gYAfb+25#hdRIJ*1DUt=b!uXP?(;7jt`B^63qYe3Ow8u(EaYkzC&EvcZj87H4$F= H9_YUTai}4j diff --git a/src/qt/icons/cassette_empty_active.ico b/src/qt/icons/cassette_empty_active.ico deleted file mode 100644 index e1bf61f612a9628a4416efa842d21d04911c7f65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI1y^b736oqSz0U-iAFp{&~&>?TYk`Oy^$2dYfMu!gl2o9}5GAS9uLu_t|93g&| z1=$qmRQK0YQ`0pwJ=43A@!nDInR{>Db8c1lRJVFVI0<*d{rf?97QVe3!dD@L2M;>` zhmS&drP#xVo&W5U5We{|gtN2Gf2q1(H1?5d^i>R9ToBGxccewtb4;a*p;awM$CGoI z*S3kOu_?3qn5Q4xwr#4Zp*3su)GU|F!~v%95=i+i^{HX^CM#>gZ4Z?7(s|Ms6QPrrGOQ~Pl3yKM1it=>;DUT75;ZHx{0rTm5bW*sl&=jMGz+fCYU zykFU#Ymb`Ae7?%#Q0mp*({{fheuI+i%Tua)q?{@@(Np40rfagNJ5d5qc$aN&a~F3wb+Av~^S zEHQjIJ!EWLIo{)lfpCGuK{W77%ysF5G1L+-HOjdCvbN^$ijx=TuzvJ273nkYkGUL* zd4GIA7CqNnJ8lKy)fX}TdK%;FdvWpNUTn?_e0-|=)%UtzeLaFd`f^w^-?#J#9X{8= zee0>7rLV!#{wUrY=aSjjpV;q?7HIpuk9|Hz=eqeECZl?rSn8imjkK3$x^;gd|J2|2 z*83qd>idVAzRNu>t%H(l@rnJH9J~BO`d{nMlaUFkxJ{$4<@^mCrN%BF4fEyZxO(DkT{5D>DPL2UvQOU;38fk zb!d?%Zl4@nHJ^BiWnGz<#?U`w=fb>yf4A0L+|0wAtk>LVYV+IBn;Sd!+rR(U6^QZU z82|ks#y2N1UWIt^IK;)v5F7BxiJrIa=(+1d;X>Gq;)P!%jF_Lp&UBpX;5n@Ii_4oc z|3=E=Ce%C4R@&vU>gT%pSZVUSk|X_eeazc~xNVyC?vMMJyNBcS-H+`soTAO@sK$D; z?Au4^r%C&~$!hmNdaUJro$r0_EAy{$6W`jy5&GNapXRh>UC3YO{L$EjlX}p4XgjJO62n7sz8vja|Oymi1u{%yA#g z)e`hU4Bt5&8$FmSkJo&()-dDCbOsG#HBRy%J%eT3a_&{OhKzT-RzsZHyvBs&iR05d zKK0;8e)9a`sv$k?lc!H=@TtWw^Tc-{JYdPA_%Q!62RHGlNIh8ATe_Aj$Ik7eJ2wBh zwQ79t>-;@$ue)qG|NJg*3iI>N_nXFU32y)1uE6`d0(t>)s(%3KWyEW}j9BVr#PVdZ iXhYM4u#V?_-1y>7(>(c1?LzF2>?fsDdX?V1N$Bs>Z?97NDW&xGtzUooDy6?L_U@fu z|M7K7zkZX_{k>m*MBLx-{SGlW1%i*GOFtrRXB*+SWpk)u7!z%r8c_U0ydjw5PZ)?} zW30@tJ*J!sk66M8vF^vCH+UH@uk2jMCZ4+8$2xea--u_vG`P<&^4$38=b|CQ+O_Eq zu@wf#J->kOTC9%b<9y~&Z0S`SI8}a;Pw~Xc=2{E4N6Rn9Mt+<#&SEo;>2eLGkuGep zR?;<#r5`^bH;d%~tzale>EfK3MZ2alhLe15y<(YRCtjKqQ|gm3Ogm%M3P#P{#v4xL zRy_NhZ{)7xRnHjHJI^@6D}BfJ>1G@+r*S+(*pLl0*jwXx8r*a}z>juj%1GyZ{4rT!W#`*4rGfTeh08jjakwJtdu zaX8p|(>LcTtkQGbvFbfwF^p@Bc?pl_9i7W~;9^W`5wD$F)prcfp3i&m+MF7FdOnpr zCQQ}R>Vj0(>w~x%7OG<(Vn!oaZdJ{xO)cXUU95EeUMjIT(LBd^&Q>rZ9&xFG^ZB!e zSFj8bF)dcXbF>!AbQqWGYISz;gqd?U%*?-pmvN@L5u?{~{R3RCMb_u}ZR51q8Mj(r zj;*xM>0x|IcjG0!#&?z5fS#6UkB!;f9p>-g|6q1W@5d*6e|^Sx7r(dg3Z1@(>3i!J zyh~r%sJ&-|TN+=diZzN0fOFqH8FxV6nsYAW6Weg+`;1hEFU*N;I^*0D#|F0HBfjuV zsP$QoV*y*a6wGVzGqz*Yb#b*O*)<-;CpJvj>ZMzK8NUV}!K)lugWq$Wk*#xG_30|s zU$H$7&84y@d~dAeV0pTKdFQnn5Ub%Zz4EPhwC#IhwaxAa4B8$In8GeS=la-Un%`T< z%i>#nUbnUjKj+-W{>S+I9$Be zDosKM!pi$m#OFDijkVa?4aU*ICP!{9=InY2yTj3HC&dgej%{HFj)EPuuj22;4ji^7 zs99{4e#e}zr7-sPT$i5hh#x=Pj?d`^?_Q_z5qd7LGi)e!8q*J0^WPi8*nk+>85oyz z3yjzH9`}rQvhjnzhutUqZW5;Vuz|n0e0fvdmU=Pt<~4V$k2S`k#D zW18E`F5ZSy{NiSB{E^p3>Z3Hdj&&8}Uf_-6(!hM#Ovl!dI@UBC}a&u5vq)&DE`bIoZWy+*@}^AFs+HAr*m8F}UX zCybo`ss{P`{j2-<*dB~~Uw937R|9<~-uC%bG%VGD<7`|n!zUIoZEU%>Ao)0d%dKn2 z27a#@uegaP{v8@j=Q?-LfLzGa8abnhKaMS(Pqi1%Qa{yn2}|Su6Mnuk94dwr&Aq+BUvUF5)PQ@pZDl``Tz9~#2J*9M|K~W1WzEBNIj8Sb2j^5C z0cTT#xEp@`d{Fpi8lagU=}H2mV7)jVUk9_Kb+LvQZq$~SP!SM^~Z`Ew2S za8tn%e(Gi`eUH0Y1J5<)=6M(H@Uz?8H^xopm4-HV^0TQvS+8SH+%MrT`7d$1f=0sv z_Z9hDE?eA{hMK#VyK1^?4fb*`Xs|uUyhHB0`Hyl(4Yntcp}3FmJFh?Egn3O*4cRvH zpEzI6+tV7fNK@7KVphh+$8Y(^oZHVS-8|!01y3;iJ|bOU=WGLd*ol^I&MDnq@TVbo hMdKLehU~}wY$NFgGq>~x_8mAL!1dn#;Q@bJ`Ul!N$y5LU diff --git a/src/qt/icons/cdrom_empty.ico b/src/qt/icons/cdrom_empty.ico deleted file mode 100644 index 45580999cc66d4d9a75aed03ff9fc268592a28d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmciIF>d5W5Cu>gSQs#zY_P$G3LW|g8~Fx=LOC*g2}24U`Uo31ut$KEI`Zlgy2J#| zln9XMYL4D)tA}MU7lbL#;Vp-Gmqp{FiER)xuJ1;6R$V;^tAe zKmS=n@3?B=R4om@Fl)@!wlrwT*LZ(64BM+=xH%n$&1GO8xEY2%@Uq~|=ehhgc(=j7 z`!o#YJ`=Z_@qSb8S7rPb_o!zK`Wfy!tVshNqeYu$M)@fm%JZf?clz^T zyZIE)sq=VF6+8>P8v5J7y9&qnE|0&B=h=Nc*B;_|SDst(3f+AlKb~7Z#=G>obJ0bjRFPa&7i0h&9T3nCXjI{Mn8?N!lnt9&R#+&oNX`%k*^=%HPJX%~e z8JGCA2QJK7=JHUyh2gOuYM>hPAU?Sk#qly${0=vxnwqj0pfC2X=1_XKF28el z8B1M`&8)*-J?R@i>(o8T;lic+4IZQu+Is24aA4N97xFEnH`o7jwRzUsj`?P7@wNTa zn?hRI<2AJT@qo0UJ;$X3Q z_pi%%@9N{d>k;_e!PcWln*XnKI~fy zU+$0;^8V)Q!#Q^CM!DXS((zN?+0#6G>p|U1df~Bzxd-0xIXx_S%4ctJ-td?nXskth zj?WW{uj#>h)GQ&s9(clBKi2~-m}^_}wchHddeAR#sHTOPN2kRXj~@0T*U*G&mN4rq z@SofxGM6{Zd0rVauQiXw@BL|HE^jE0Uule5;&@9~PQX$PZ&-Pj@_IbGhowGw>$Nsb z$72smdh$`b_#TbB!dolH_R#TI!qP93In?VKy|rAtIp4?JtFOQE{^INBZ7*YuvpwLu zX4SQ@>{%;EOWwTIgFJ7jK4YzubF^CVs&?Fu%;ycWPF3IK+C0y-YoB+#Vb+Nr_Jb$P zTyx$nO+1JP#l!gEI$Grw;lImDxdw}kkW<-s9sT0EgV zExfgOU^o%r!4rz}hOgVY?Gtv_@Qe#dAZi`ETW-j(O8dFNjB(8A20 zn-B5*&iD@seSiKCU;Nzn{n=f7@pIevr`z}-B0i5e-E2002KIrM{pn4=x!P{}v)jPC c&v+X1%k2iQp!&d~S9FVh@!9=DM0~IGAARs@lmGw# diff --git a/src/qt/icons/cdrom_empty_active.ico b/src/qt/icons/cdrom_empty_active.ico deleted file mode 100644 index a48371bd7b0e0775308bacc103eb0cfb7bb16f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchdzi!+{5XSdxCq|IME*!v}Rl3X@ka`{J6OoRG%XTSNr+2tNdpA^C>JPFUA2f?%O(~}Us4I#XE z(e(fLG=$$J_VQ)ZfBRVoKYkv<*;&(nCwYGh_qF6mQxuxGKv+xOf+MwDi`wSwNmW&q zxi>dA8Iv4J`t9nf$*Cllv(f1^d@dR}S8}pel6?NDPODMM#a}(g^0kPP#u9(8K|f<# zLoP&q53 zuYuv~IAb7M?Vbt5$pztwM#mxMbBU7+YAy#H(EAcMxhLzRI&koZOB@txFPA#-1--^t zZb<_z#w{MdNon^>N?ZAe)YS)!U#E0krxdpmSB!$!GA_6i+@Gg(c%PEqXXJL1?>BnC z(&JaTN8RCIO)P5LpG9fr$vT7W8g`!@K0|y4hXhBps)75-z%FpHO3z;kT}=M;NX5CPkFRG z$`E_l$o212w^c1RIfh9@KBC=%8`-r5-QP;p~d~v zkL$G^%F`GJIcU)*m$*lGqQg9p3~+s2Q<_6s_$<|;hOQ{nKog`ckX&%6E+co+^qOdZ zOSBM1(<9?UnBIJq4p*U~Mq|^D5PcO^W-A2BTp8UY=JMX_xU*Fr}kB zziv0pb4y;K!HRl>YBl6x2Zk|y!{)bFn)nuEBoezd_sO}Su!s_bxWAv5NsSPx!0lr5~@iF@34#*P9-tasMX|jHD5Hy&z`OLxd zsC*xzevomYvQ{T`d!FHU`?bCEyKTgN* zR_X9Ar2U(ac7j{MT2bQlpN~?!{3O-4wP0-UXF>VGU@Ko7GD*fW}{s-$;LL7A5pNuU+zrKEdaE;r&+jv&u?avSO%=X9Id(!WD zbSaH@vPyXXAz#tUzdcnKe3{$3kz(2r9yxTprV|IzRsc!P|?H=p5r zugg64*BBaqw9xj5H)uTl{i~~?RENg((6z!xMQE2W=LnBly|L+c_xx<+eyFeWo_vp{ zrWxLpq4!oPcJTSro2ydsm_ng8+L|zMrDbA8|E`v0Sp_;`a} zM{4K}G(gX#k9SEE9taO4F2=omG}jxR*F@VRJn&_CMdUdF)u#X|^1h;~9#`Q{Y70+*0_2#cf z@#5bv>dm2!7yFp;T=05V%l8tomM7mG(h#Vco{^ebf5Abcb zv43%2ln(<7{jnw_QwiiOvlES`K1E;70?@1y@tMmzJeo-I-=Nq%~!8!B1elI@z{?-uK65>Uxn2F z&LIu2@ei{tKIgYN$91&*JoqU`K77_X=G^75XD~H?q7m0{*fura9BkrKJcr@Z(w|E# zZ*Oy97o1XoQh`!||F;6F_f&u1QT=s*JJtzw3%!6|LC>R~glA>Kg1dr$1M$-Q=@W9^f`Ee{Nda#zG#MbEv|v#O?-tKN%aV&vDi%qjdTE?h4E) z=D<4Stbyn5w$lYJlfyn|!qcRY_%l6&eSQ)qTp@?Vwq JIG=Iz}toO8oO=RdsSt3*)t*=xs1<@uh9F0xv!vuCJ@GcRB{KsOc~HWN95-x8B9V5LrxSwfWu_sqwetg`!M|aIOGa- zSfG9XAr3H1pY7dlmy{O$rTo;-@w4A-FdsDz&i)erfe!tK&~NX5jo;hGxhee?8+1-d zpX=BlS$^(?oH*Q+KKsb6dkwLT>-|2%oRWTO4->0bUv{_ci?l*U*E4h0bH?6{EUmOuYXrkZF`r2 zcKjheFb$9GTIs>#{!ZEC`+D&nyM46Ze2#r#zh94*_*pDfm-C3=_de&Z$MZQQ)h5>xJk_84BmP6g zvv?Nl!<6H5iE&KDEbikx69vLokXyv!Gf@izs<3ACY~?sU%LMdk65wf&WYCjZ}z8ZVwCW8+>Gn3E9a(h zuTf{??`&AYQ^Zf*8ESozT{(RAo86j!r+r*&ALL+gwcuNxuhp7+>7VmqF1}(-IL3R% zzyDwBU&MzTl!o|YTKb;F^*8;Nn)AIVFusCp=G!|w`8!C>oBy%- z&-ir3Ao2b!+5e2!n*6o(&W)Q5YLC5VuC{gMJid26|19<2V|zQSUu|OCA>=CY=ltvG zCr>Qi#}dD{dDV8qJ(f21_}MeJ*?-!(c5%Mf*5BKCs&;YxBU?{l!-MCq{jO{s&&0Ci zKgWE`?QS%uj_;O++ruB8nu5XV^{C{T3CkRhYTj(vnoeFM+!RP-qG9+HQ2eZo#i97w%NU}2$bN_B^RN1Ke`I(>Cpwgl3^cGT*IuS5$^#wk`kwC4i>~|o z`vV#1@S!7Rf4vSmy1W_)b95?=XK>xv$B&|UKUoJ=_IX*?n@wFWPr=8!);=Tc#`hcT zS315)k4lV#+z8*Pb4MKXl~~`gboh~1A9yCeRkibeRlOb(-lZPB={@Mt_}OoIMlRyZ zkbmtv9_uxR-o!Ec_u%*S<>xQdU+X75Jc3QV4(%^>bk6!iXD+7v<9#`X*5=Ur0gtZ9 zPe&5rAMy_xJgZgVb+vt^^z+qfO>MpkjSpK1Xw)K>KcJ9yEozEdQG^fM@&H9r&M-O^+zpejm&oyUg z^j;5N=*`%e{g(}tp*aT0&A*-hP{(Z@g}OLCKVJXjk9_7L@~Qm8GZlyGf2vO8Q~vWl z=OVhnA^)-4<*SZ*8*vKl@Kk$XzP`@K_|jJ$my^1A2^4e2{zBQtn+Fxp!RxAN@USA$IQM z$33jn50~+ge9uJeQtOU$Cd8T6?B)2b+o^FX$&$wMqP}jg2Rl5B;E+j_&^)KXPB0)GP^{{RswRxWe!t?OzRWQ5^zdaA(rx3#H*ZugXY>2ZY=1N#`)Lt+xk0!xzf9|*E{D=hySp?^<35|ZcC44N z3yt~GV;p=x-QK!yXH7v5(0qK{nLmGu)5i$={oZ|c;BMECBP!>b|6}IgZu`93?bh=j zVC3LL>>sa#@jod)^{^P!4?oq4`ER#<9Y!AT0ed~QR#@U7^E#1l0kOl+OosgEPDO<$ z4nE9f4Y9*-ntvkm`YXQl)*OjR49W391~$#L`_y%F5M$I2@?rkOy1BVI@IhXZ|N6R* zK|bcdn3$RzzrpL6A0BnwpXfpP-oNX*w&}Xcw#WfW-kQA1;9b}0oU!A^&l{arY9H;4 z%Cv*pm|box-BS1P%;U(p6XJO^>>c(Hdr&!uMSXX>z4O{7XNixSh4UnHE*;xb;^8*L zn4;;H_>Fsf{j4$1`Cp8u0lb^L&a~|MF~6K%x@lJ$>}Pd4 z@qX6FXe>_J$Jn!Vx33+KkrrKP`qiAT->akw|?Yk%_AsQ+D*Z_l+B#~ z-hIb)6z|c)`{CNS_hYSF=ox=>@GC|9bNsP+DCYP-G+*|t7Q=` z_z_2rsSca@b4KkshWlmw&O&bdK*`C2EFBXIc^V6S%5h@9${$~B8N;QH@1W@u|)ORM2-!zb~*%^m$UwvcGQ_s5U!$sGA4qf#=9HQjXyIpHo+4xkv^XITj z%X4L&=deZ}F4tRjpPAb^dihMdvZrwZ^#V_QP8;77*uRc_zQ*#TJ#rzBxbU030UmqS zTKs;Y_~hhyYl`S5c~ubBAY4lCJ#KHY9jE!$ev5~3n9e_r1M?s6u?ycp%$R2dQ1d<` zzeO77Pi~K6@>8)WH#LbhpyuQTi{@W4_ay(*{Qm>jUl*}t4aBu4H#PP@Ywy%`e_(fB z{?+rZX#Lw9_^u~TYIeHJ{(6n+j4S)@(dKV~Jg;gSYe7Cxa&_t~7kD58&ze7V(4=Cn z12i%5$t%-Gx&9W%=bu4xgEEB&GO+kNY2iB!QA|@`C53&{J&Oi z;{Ma;&%SslGT#(S<}X|8YDEb5G-yuGH-?q2Us_N>ZZJRJ+2>lqG>SZs#wzcmP)dTSEZ+yGzegFUf diff --git a/src/qt/icons/floppy_525_active.ico b/src/qt/icons/floppy_525_active.ico deleted file mode 100644 index e19baa8a2094ca6d155472f1efa9c38a706e80a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHLy>b*W4A#L7KSPl#Qly}`k}^-ggoepuP%)G|!j@DS9wQYsWga3AkSAbxgGHa# z-<{TL@2+?ExCG8O!nSPblO+6$dHac`5{@@HC5jGg*xmYI7_fUhtIQVZw>oQ269R^*YlUidmkTK-u$Nasqsc0 z8{;ATcz-+}E1%1)G4j|`RaG)S4=oS<9v@@x1CP(WzDLsZ&AF!G(fBk}x$)|*u1Q>v z`)Av_MxD`eWAz603hlers6^Z4g09UT)Bdr&Vd??>9pW9t8ua9H#rqv&$f2pW?hhCT z(5E^F>m2PohJDBIpN~DyY=LqAFvdgnA!hI~8}^$l;_1lvBjT%iI{FwN-ych#<#A)9 z<*T>JkH^~QW%|aY`iAagi9YPj)pOc>(%1gZz%TF#d-{(&`i;H!AI2%d9gF!Xp5G&K zrg^%j%8iZxRo6)IS~Oq1IKyC2FwNbk>BIyRfCc70;KL!7V< zokMqsvGe_|=5@btO+5_$n4%xL(bV$%59gX_e~Es@82w$Pe@gT}b^nyukG-TmA6e`R z^9OnnD>j>lJhEhR{{TDeAC>>Av!y%6fId&igQfH{r{exG>4$9zAGQ7-nPWd?1BPLd zm+MRXlhe`1pQ0aimei*kYo+?JA2ppcRMSuTyYCnulgH#A*utFP`-*dKvmbl=G43PO zv($Qy@AvvU$#K=xOV)&1-fDe(?+EjFPip=_>>ak%%~wi%hgJBG%WfN|GljDN&--NV zm~S&ZV(YuI`^E%&dDpQIm_v8o=SSbTg`0YTRlzRBrL9Zh_+znB`2?d(4Ln>NomQ!doLHljEoMk_VYwt5OTAJCWxPA}@dM M33KpE+j=8^0H9Cz?*IS* diff --git a/src/qt/icons/floppy_525_empty.ico b/src/qt/icons/floppy_525_empty.ico deleted file mode 100644 index 8fa6c6b87c333dee1e85e39c68e15470471d3305..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI0J8soL6ov;WLP9htQlz{kB}+)f4lGKj5F4Q8mXs_Z1qE`Xq>U(0HjzyPiH;_X zIlrARapwAX9?lDNN4olb9{+ib@7Qt(&%#dF-3^AT@Np-EHz9<*y+J;G9>THd_V)+* z%Zm^`ybNKr8szWB`)$6jjANG;VbB|d1LIAs?n+mSVZC1W+)}i>9h`56hkXnWJ6oy~ zgeM)>9vA)D*;yY0RJdF&c|mx}PdxH~_<-oax%{#zHY<*SEW4KezK93vgOXe4IJ=unvoF82BBgcqc8FK??(LYrE@gBo{!d~4)Mw?)zKh^jQ$O5XR4wGm z<>bzixFz$41Ey*!sh^l&st^3O^@rf?L&^M!!Ca9̾*+C%wh#r8qFsUQ0__F`QSLFHI?z27l6Oh}OKa8qsG~MkEg#;J z{)qvW_OPUXa)PDzFuZO5_5Xin2yXZPu;?6Ia{n{y+S$X?{m*qSilY_#586$A>^GL} j`$J>jA=-RAZ`z}awt4%fX-_T(l-!uUD30Yl{?Yyg5+_;a diff --git a/src/qt/icons/floppy_525_empty_active.ico b/src/qt/icons/floppy_525_empty_active.ico deleted file mode 100644 index 703d2a64f6d3a3a3ac6726d3411e84959eccd8e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeHLF>ll`6!ujG2{E)oD|O>WMt;JvFn6fc5hldQ!c0a+e!>k5l}~C{#84eS;&$dD zF~QO$ywAyZaeQ%XCsz(cjnXf+-}}Dzo*gHgQWLeW4iA;!RK3|(>V;D3=&0&{eyG%? zjGdfR{SS|ndi_|b>9p!!h~E#feJVb3D-6}RfSQS4M=R^G6oid?S=XW{tZxKMRfsRI znuk80=5x!@iQuVL9UtRh+(eEe zKHmF?IW&K~udh#^lxBWV>e+$CRgLWHw=#cwRqA&y<$Wcn!?=)nytm{NT0N7C@2ywz zE#1*t&xp(q>BGmpAVZ$4I>3>2vK)o*_*cU{__C&<<-Avt^w0A#yx~|5N;|L27Mihx+qAgs?&L z=d01pao0}k2l73&SL(A#X)aW$PgNT+el7Fw#qQb&>I&rt10z2i=sx^z?048y0-4Fh z@2~ja0)ex+B4j(^p$kPor&p8I4ZHk$n2a*^>ky2vl} zIq!{4xb6Gj)eGGt4vAr#`S*R7h*JAsqmT4Q=bxp`Na`52vi`!ATzgL+`Hzj^U(bK+ z{@;22b`dl7z?Swu_l?DzJ=o|EKL4nV)Y04+LeGMINaPRJ%k|G)f05%m#A@>oW8i+E z9uecXc#eXHad0e#A?;QS=+s&*lwtBy7p4R9hg+~wBZfk7XZgppN9G@1e@QB)&G{ku zyT0B6*qAsU!!h}j8}ZjMWNEwpjDur;3aN|ubNBzYVnqEI$576p{`4D@KRJlGIgH7l zn#9~Sq~Cr1!}mXHNW5SFdDb~NX8*I+Lu*ez?0?>;B7D$%`)YJ^+_!W4TAv*oGvCvC tHZi794JuXjiJV_f%;MXgKL2@au5OJ!|E101#%R6L^1FnfPRGkH<~P>c0FM9w diff --git a/src/qt/icons/hard_disk_active.ico b/src/qt/icons/hard_disk_active.ico deleted file mode 100644 index 9946a7f2e14e25dccc12b695f445fa2a63e96706..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmeI1zm6P55QqC@3xpilfdglE2@;{-07pCrx&R^Z21FYY@(2zHECOQ4mc-9t3F$)Q z&;eqouV+7BUAt#@W_I^X;6Bw>cURZ%S6$P8X7@_DC=bh%CnfY%`Tk)k-;`3GJ{{Y? ze^$zG(f91x*#7B@Qoegs%GK4_eieRy$JnpJC#r!k_J=Aj!tcm3guk*BYABoVRYn{! z#O&+vp@jGCA2@+=eSLjU;N0i`%gdL;X0xe6y_LEC_}$#xRIcrITXASp7o!^Eqvl~3 zKYolsEc8*tA-?LvyhE6`^VeT4ebDq_#~&Xw?L+?fF7;=;F}HcB@&EY8BtLdJ<#j&T zzWj9u3yfa;jA=2zv0n^x(9R#sr9%E$z+kNrd_Q&>{)#8|=P<;Qin+{_%|(68 z^@DRJj+=Vka9&Yeh&jB#RM9Z-R&$B?xnyC1oEgpShYFE?m^I$xFJ!V|N_q74`JeE!eD6BGX|^ebSRGy1IO{E?Sq1WfQk>OCR%F~+snA89!D;h3x3;j$&#&wdn;a{%kvQLt#9L9`V7VApY^F|?wn2U&#B#d zJBq|J@538z$C@=w9_He+4?X+xo^1DgwjG1-SyTgz58Lv= zvlbsL&tSFqo~7^{gHPOIQjB(nE#A}T@G>4Vr!Fw@ww3Nx!dC73l=3~ z(=WcZiV;}gWpPdR;x{%ij&ObNyevcOsCY~?)LD>-fPdQ4{TUdB&xhgP2gC5sMZ9~B zXLfk_>=$YLwwlVCRzcHF)v_+ntW=xNp@3;9oF8Fi!&4c_s&fGV}-F^pN z!k=TvT)7T!=Eeu<@oJkpf5)Tq^T_o)hPwM|pU&g*`RiQnLmOXy2X5zb?lv*VANp+H y_4myq^BaS?xepEJr}A+#5I;a%#y^1K$A~u%HvCjD%E^NY?6M7c6ZoF#=>GtO+SvmD diff --git a/src/qt/icons/mo_active.ico b/src/qt/icons/mo_active.ico deleted file mode 100644 index 06b788b4d533b13cbf947d59592360fc02d4c612..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchbJCYPf5Qb|b2qF|Rgn@ylH8FJrEY5+Y;BklDHZg$EF=X-ZbPnJgxxb|IB)H52aj{N9DnYx|$arF^!&XU}T;{V%2b z`D-cH*R}n(`Tc8ipPP?W4Wag1QC^te$}?O4Ifm0L14H#(I{swSWj43ZpY8eft@=`8 zZ{K#qhsQh)f8ZE~^Drp?k00mx)2Dg<`Lmj}xBLwQAP_3n*RS)8fd|GB|L!Y(eB|5w zX-h*TGODZ}-RPi<7_^(Y4}NCMUBoYcv{l^|~-@NH-y@(&J#0qcYu1j0<SPw9WS8E`h++W-+7U|&QH+>cZ z!PGT{C)p;R=4LDs0%qiEb2stg{ER7$snmPP-;eDb)#FKXiFGQ!+wgDQrcjUlTXkVj z^4_vf=<u5&JI z_^6}b#>frNhWeU6u!J4;gCjiNv*BHPHa>XhhL7At4so}>v-C%Nx<^79}e1Z#CJ3IE7so6z7Xjj=N{pMNq&fB?On|n#(6MJU}bauj1OMK7Y;GR_lx@J zBWBw8VLaj<;mem8&M`Q^;GAcCv}jywjD90*=72B$SX#bL!f#ld?UO-gGu(*X>pJV&oA9fi zOWmXTrc-JC&MnT-SB%EMH`~q6y&{ty_C40_8Dixz)Z>5X$o%OXd;Gf3#HliIqv7KG z+(F_Sm1t<+cPDWxJBJ*Q49}hOflE8)BlD;D@5A4@#Yf!m!>PW^AIDD3eTsjTpM3>C zInMkK5kDN-Z`bCgTQbXG}#=AOe( z{145KR%v7nE@{dM1+VN(qkoNBb}Gi<1)58DtLoYqSs5A32F( z)E@COmo=t@lY3v>(jh!B#itT&7+PiEfg=r!YY*AlF3!LB;kxhh{rf?C)^LoUJtzIj z1KO|_qrRQiN|z6Y@`ncM$Kq#>_%k;cm|^7Kton^J{OyWvw7?zr%_#rkr&P?8;-)k# z@$q{n8vVYeBmfKyZfQ8i&phIXNBoid6n^{_2O1)G<5}!K>4l$h@}-h`{Bw?k3LT=T zdemU{$n)1%Gh_}ok*4#o=1+HoG}Y(+^zDr+FJAMB)OcJkqvb z$LD9AR-*e>o~BvWv_`wrG9RSLqcl?k7YB|s%|~axt6XYs#XRTp=^3Hj)M=bEU-r_Z z1?AV~!-2Ts^f)%39_R5??bLN%H`Bh;&B?u|dIH?P$aX~LXOfBAR~M_TIV%%>;O=Mv1i zxaNDf{Jwuq{n0&|7rT%>R+MTxBbuO)(`!=^pRt6-*nz<#m%0di>?`+ zn$hd5iJ|8+Q9Y4vov*yFaNXNt&zd|h_0%~wKMlRKp?vb>=kt55HtN~ZHb1>OH(t}u zSe`a-sGdltJoxH?*^?ewrz2m|eB{LGA%^>~s4!^V5QQVQQOSeLg=8zG9eKG%_!y zGoN2Aaio>rr_4{A|GAj`uQ9(ppnccQKmSBMkk$z8J)a-fc{~;ML9@;0m-7sX^%S>e z>Bj=ifM>t8`Q=iZr|%g)&w1g~7FRtr)yzYiCcfDGsf{-++)0IU=^>_xSMyb0YU8UH z#~f2|EB*y zaJj(Sh_gP9mwLC;_ppoZ^P&Iw9(G+nT#k>$^VMnpRot8x$XonxVfoO``(_k-rbamG z%lnOQU5-(WmgfY@L+>@}W>X*GDf`nLX{0xvKC_H=JY|2HBQ%3LZ)gT}So@cM9XTJ) z7V_qms6X|~axz}=c5mq2!t@kpU!I4uPA|RoN{x(@r$2eQKi@hBYI@aDJ2f-bpZQU| zwm&X!C=YohswdjfHL&9;`{xWiX+in)9>w$hN4>luuhf(u>DXW2+WuJ+^B!sAnL#{4 zyi@k4vE_|NTMR#Ee;Olgb+|Pvo&W3p_Hd897Sesm{_a7&v=X<@J-(gh&%atCZ`z|7 zM)}mkn_vIrhdqLQ{d?a^5zOM zxx!Fc)89^YZrA**7FyB!IC*|3*Qt@T^^+_o|mQtQS-^YJ{S<0U^ z_u|Dq{_U$$e)+nTmoNA6+uHX}t^Ka{)WgcK&sQi{weQHbo7RqDto3_qS+Cc#9&y55 zS=V0s#G~fp$B&Hz{&92D;)b;+w%UF87d(58wirfmy?_6{^?v&FsbOdy>yO^HUXea* zTqpYV($`DB#S=#}QvbB`P-XS-3~`A0aQ^i5-sNUJwLpy1xs9=Nk9dT*toQo(&8=2m zyri$jxg4S1C4Kz3V!rTKw}v?TbvzJ<8LqFdXB>Lf2f1TwP%osfzVDUO3+2tQkS}U7 zUQf>@%2B@2l8;ukWZM+w6SS zx?^#yE$xloJUGMyJiL3>mD4`)>v4WFy6+m+-gYeyZ==Ie@a{QVQ5enK`5s$*KVj_n zg3CRW{fXOsTYEmo-;ApbaGGy4BQE$k{+u^lvv``h4c`4Z^`6B6UFR0Zxlg+}`)eVG z1M-Pe4CUjpW)3w_tvGA6>s^WP^#1f%I~Qs8{&0Ceiur+g9T)B1AMd9ybJFhp;mza->nzN)-vLR*`NNh6$ePo;6H?{7PIBNSnWb_wvUW$!lU3v0;;J&@@Tu&Ne==p@VoIZzo484QK@H5H1 zO~bPm-0fcMIrH(Pk^PEC+)d*G{F+=dE zuZMU1j=Kj#5Yb_%`InRGa^~d~YELVg7xh8jdjE2sA+esQ4KH<@ zArI=zx8z?gbJO%a!{<3I^|-~co;j`YgBz!MG5?ucT^qO-1iFZwdKdh1cc zhc#%9%q<@EEphXO8;&$^sLL4ZBhFmQuX^#wzq+bX9G}AL>GuG2IhKdPyQ$Lz>&(r`9n)!QI#Qb!+?SxFvInC_Ja{|@D_O7Yi z?VeuJ&AISVJ)ATDNOPtgL)=e4I`6!L^8B<$c#*bqaX1Hy9!6R@fAP6r(9iFp|8xGV z<$C-4%Jb&Dc_Z zY2zMw80GOmb^ZL-GSZgM9&pL4hx(xUrTKBVAMT5^A?=Jy^Yb<8pKJ`$(tH1O7(^4yjBW-!}>(AQq z$L6P%5f?3Uz&t;#j9vYm`PE*k&6D}_^~MW%t$6E!FEx;tbLYR0Hmy@=PF|tB`A_l0 z*m~9GSUw{y_0T!Z^*Qe9i{o?gI{n_DZb+UlB}BnSjV@dv2}>+`@VEt z|56yJV>-3SA9wG_=vl`y{)l|K@`3E0jFV*2r3WeKFo1 z-||)&j&H16;$8Fk({tr;9=Q_q58FguN2jOJ<{%)esvKW2rbqa5hq{dsQ4?@ zjnFIbYR`yATHhK*bfAp`Py69tl2s3C{yEmUN8c4ct)Cv?1H*X}&$z1k+XVibo14h{ z!-o&Ol{)ZO3~*NJSS)_zj~~lS!SI>pm^^mzX;mzXKixHyQG=1H3BHi6i0Fo<-Mo&u{5`TkpuQ_AmFaB|exq z@6;#vYihwlV!!e;rsuZdZ+PsFbJjdtV-tfoc5019--+2IUI&9X^38aGCBLB15a+So zuJFLA+C`s@g#|}uqxx=7IWvyO(>+Ub_}p8^t+T`<*rneG#s_m9M)qesVy3?z9*WoU zh<=jqL+~8CWE)Q|ZS9!&bzECr1>ecf>KWdD2gOBwK&EH6M z5A-{$dp_1%&F?Pyp5I&g2wlFB`uEm%`Ye4Ui8B?}IyowzL4v%Yn<5#au@tOOKu@%4FMddxj?J(}xBfM3P;~YFYgu~dv4*_G7 zRxbB^b3K9Ga?ki0kM2&M!%c5E2jZ~^zD2EAhA*3P&uhjs2iS~992J{f2LWT7_`KO` zT;D4=oW}r~2FAxOeXfAp_ex;{mNBsjZZ^#L#QQs_zlRzhoADXXz!n@c{K@xR<5R<^ zPY2?+ydqcn<-F~8U)p>jf4>5E@wteg@~SbT=NogcZO$U^^LQ}=PQS0Qfp6aYnag9Z z)jW(z9Ma;uc)RErm49dcnO$-7zErFf(P;Y*`zv2*d54X0d%tFW{8`OC?e8J{U{O3a z#>}%SPp{chWmHNXO?T#YcZd@<+*5%kdaW+c&{8*chC3FcX6Yg)(xlVZzVc@B1a|K1Fqkx6Qbl#=)sLbMxG(HLX79F7Z0A z6~CB+pXz+})o$WvEx2XDobnrgUH|cWPwgu`Kq{_tS(n3_0ZYYgw|se^}p@WALk<0^XtGTw7m&J4nFE z=ep}S_v0Yq6y#bCu?c49p`IugdXk;pUzO9h`cpyE^69>mPj_SO%1BN$LrAn7^^dH-s#(e+) diff --git a/src/qt/icons/network_empty.ico b/src/qt/icons/network_empty.ico deleted file mode 100644 index 4a1a102846ea018ba6d899b5352dd9fbdcfce858..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6950 zcmeHLJ#Q015S{qj1WO4@kuoJEKY@xW1qIUsq z+(bghdow$GXI~r%I^cF?&+dHf>{@wmHzEhplcOVn9La~i$U6}^IkEX@Ao2;i(^H#& z!F+Kja&~6(k0X)UE0NcTK?;Fd^FZuvM_BCm_*l-*&*k#+Qf9N6q-iQwS66a~J5*p}fFns2#BrfZ_;>&<0p;3`NHk z6Rn_TXMQSU080XbTKje(lI0>vBC^UvzCvb@oJUDJ{Q!GOx-E&bfM&&8;`MXQ@wJYt z#MJxy`xaN9JGj=?p1{9-0v!NYfUvO+2(MAuQD7P1o9NmhZkn~L3Mx5A!)*{l_Y0s$ z+$LzU$7RgVmOv=iV`nIrQ@=4&LdgYeWlYA}sWe~p@bC`QTAxPh*Ff{?(7n1^XK)z< z=mS}J5dDV0=s-B8wqgP;nX1a?k&sn|TT1hds&ccIJo^lse-E5D`8~Ul2c6$+>1i*L zwPf?P6w{_$E!T?wxRT2oeEyUN+Pii9dD=mH0{`y`7`TW1``wlR78yY>#O)Y3N~AP& zR;H?}okspu`kQp8< zoL4djZ*fjZ|2bp|Swfakt}x$V{+O4_V`o_UEk3`?W4E`r?f-~yZf$E%pgn=c3D`TL zp*984ukmLbsQQ^*nI7&P-Y3gp<>h1?Pxh@OlghB}cL$3zEvF41wqn~b_)&21G9$ejCDZIQ>v=*26#ghPljYEDIX#e8XsoIL2O1w6shHVQQzD)w z>)RVtv+PIwW_NDxI1$iN@9VCvdhd15-pqPr=O%8??e9Cq z1NY&cbGMyyH*SRaPp>%lqsDID4D&Bub?$@LoI5xO^Y69p56yi`Yjmg#A+F#KweGyF zEK7-MY)p^By+dDHbLd#2?s<9((G6%GsHMc_-5hDHfE zj>d5jeXF+yFZvqtd+5_=-D+t$2Xi>cQ{;T2P#97}4zrX^huZt|d7J0reQt7;yDgK~X1Y9Wo{rqBraTdITIc;y+;IpxD#LdsMSiBy_d{0t; zj90cpO0Mb5zKSW^g5eX()^rSxKe*UU-PUs z?bKNYV=(9H=JedHkDLQ8koyowejl0u_ho9}(k0HsBkNJz%B_(XX8MU9+&L#)idF+Qt5he zIFV|8U5dMJN>x>|c=t?}4_?ShUnHy*~s4w zvs>TlGQE7hOW&`fZFI&tbpMuXE%p$PZOJEee{9v><$-GhHoAlU{t|8W4;R{CupeIo zG)m=(`_}J1XVIz6S)mEyDXa$%>0Z&aXlNbx2CoSh`^_=;Kt6Fi7=KseEU2q7*)RL* z)25a@=BWprCFjmHuz0)Wzpry`=D8Lg+Kj^^aH0Vxb5I$RYeXLPV4g?356$V&{o6IQ zd~F`_5JKZV@x?yjWDcT9K6%U|^~7UGJPL&&9J|gzvy**Omm_(^nS;bZjXTC5`v$3H z-yr$Mv7_~!OREe{v_ax%gDrwf2%v?wQYL4QHhDu49`d(YC8y5=>)SXkx`qZGn6v*8 z{DZ#-aHFa70e?(EFzJ3DpV|FN#^WJbsj<`zcl%A!RFB9~A`uSN(KcvJKE=3VU&E;KD~4QyHQ|^%ZZUuLwdj)nvAh z?3ibeZYE&Zoyml7O>VZ+3t(hxP-@X z^e1ZhYPMWYC&c0Umhehg!WO2D(HUmkH}G08=bX}rw}rU}uZG!#mwmUmA|_QG_G@uH z{Ft8l+IkQpoU_$u&$ouhIp%RWUnp-ZbW{8so^pLjTdWHE5AD-?M19xc5zb0!9ZP=s zHg6-GPw9v8DZLpV(zke5O)@}JQilw{I0K9CEnK0~_Yl3ee!^XPXIZQnaM;FD>YIA% ze`h-%4_`Oz;W9rd-_@W!hSmLk)t(gY@(nlT!_V`(pfWt|p#m=VJbh$==j%W62aXo( zz4%q^aPE8kuVUkzF?V`744-Eh#bdL62)@Ja<=}X&Z80`ECLG5?pQZg=G!N@^f2#dpIuMAv~9j_^lk*;J0vGi@(Lug`eYRdkb-F z(lHm-;vdKEdH%ogL(a7L*4pA6YyLClZhX!q$|*(NwY~x0-%Uz&%QGwI7k!uaD*AmK zKH;s@_F&29*cR<)++SXdAJZM~UZ?R9Q+a@#A;T=EV!UBrZ6APl1}^Vm_mFoG-NOcc zxV*kp`5k;|oa^qY&R8*?@foPo*x~ZsV(%ICwNo3`1&2Ey{;b&ji1^|y-N4j0`BC+v zl~X>Dmjxbd|L8}>2jhwIF=*m0AYkEgbh4{Q^c*UHtV8|E);@`|s= zhuOZA%RBhRE#2$G;*Qu6f6YPM(mg&L#V>B@Rv(V!7q@ha4@dKhTYAffTkwlpy5_^J z_{A-~=EE-jd`2uk@;z{klcx(TCm(m~eot$j# zpYK!p{voB=Y-|6vx__4Y(Q52ZW7zr)(y7%ASnX4;Vjo49JD<-xytug7v8@oU7aZh* zH#aw3?rOE_5Sw^TfUmXX{s`eBKj)x^7`fNi*BvK_-`h}MTMGxXIEVIwpIk+HvB$0f zpK@s}Ha+_KlcT7;4&9#_B18}IygxCW6Tf0UKQ+u3A$j}y$AnZ(qSH_Mz!Hr zL>GQ1=Wj*s5k>O6_Tjv3*H>+Od)BtgOT)%+*|tp$TE0JL>~YgQZ~S@X>z6&FMy#DZ zvU=hxQVp z3*4uV*wER%_ubuH_Z(p#;J_{+`Doauj~VkE%k#x^ZwJYvu1ho_j>JH6B1C`w@56a~ z5u+AP?t5^tSQPbb8RPd8JxbW=viH-yy>B+nyj?F>_MV#Cd&=?L@XFp-5q{l?d%oBE zd&`c{>63kUZ+)|~^n|suAI5_{fpW{iUMprj2KQ1f?gd5ivR=h`xQCRhWY_c<%k90N zW(oHy;>NES&9iR~YPE*_Re#COdqfp(v(L2%H#kJU=i0~DUPJ@jefo)ME`CLNk`LnVM413bVv5SC zcAtLd^`$jaZRc!n+xF4UOAmH#y0>%Iruky$r%O9`HFmB7mv;VgyB@vXdHftUv(Kr0 zIEO9#i_7V2?|opj_@{Sx$pCkUrTss!mYtq@f2pn7rf7jnd(_(0kI|t2E^2#5c|$ZD zx;L6?G?aQ1kC0vw_Gy4Ksx8H-E9LFez`X*;RE#vx$22@Id{cXB{SXaNZsgZqksa0B z@I2E}G(Y}`BkEc5!|NA-zqJNGy+O?zYs2pvB5wSOLwi!Mb>12s8pBVmqUH~^;qRLt zPVJ3Nyo6DH&HQk~p-6lv4w)Zr?Tt-5!YFUZ{BXmiNW2!u%n!Hr#wM;9#mCGKH=K&Z zOE_hIxV1MnaWL{vnP0i-0TPd}W`1&}Vx*yO{;1|qer7Ta;q(7cy&|5P`MI7`Q8kR2 z-}U-_*&2jsR}IdC4vm%k#7l_Qh`$@g1UhPt+NEAmyl;N*>q~RsnySI6oj>C77>k~- zh2FQ_oZEj)upfY$X8veD{5;qXKKJ&+&!%b4*7ik&eV=e<-#<7ujs}j)sd#GyYvcP5 DJ}<5+ diff --git a/src/qt/icons/zip_empty_active.ico b/src/qt/icons/zip_empty_active.ico deleted file mode 100644 index d57860b1050ffb2520c1c04c337435f1fc4a50fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9622 zcmchczi!+{5XSdxCq|IME*!v}Rl3X@_<{gwqr&V0Bvp{7kmxRD9zmtC0+KeBq?fpt zxFS%aMu5DT+2fB~j=1EKJbMHBU9qfO< zcJ6QSy?%YL|NO?e-@kS4U_pQ{(tuP$?0&XjHGgfGFQ`CE|A*z^retsVD z?CdPHgR7;M>%h};kPF`2+{D`J>+4t(WJz`RpYk*u)WjThYHotsGy1yfgN~*?&4nxW zmB7{2)ntGA4b~ctC`A5=`yl;oO|LJtpv=MkvBwf>=e1l>JGBYYLrZN9u^if2h2yCG z(UU`T5l{OQV{Ysmrt?$7d^sdWDcVOLu4Z2K8t|S=umSAs<}m z;A~r*qYoXUoQ3+}vU&#XhEr?O#WS|ET06%X>xCQSY_)qWH-oh!e$}V-?2+6)dJh-r zOM1XXo$}KMedJ6bb>w|1eQ2LTbb&+qh|Qf{d*9yPcAq67hl72YLh{itq>mZX9Ldua zds`%rx|k?J6p4Z4;Yn@1Pp{H8 zk%PUq7&&XZv5a9 z{nWAtAkP7NiT*(jc|bY;G4$uSnPaR+vlsDf>jAZU1Gn|V4bnsN(xraol@;Kk2GsnR z&>((`kxTi~OA6r~;viPq!}i1;(@#!m5Avu(W22;<}S6z^e^S4u0%ikT#9gmbM$Mj?xn0jL<8Jo`ia?G{1)j+K8Qbx z5&??DELu)$kLg!lUAAVet(;-^Jbdy`!^8Vcxc}(F-Kh(E!JVL26u=$i*QGr*#AS%T6){7(=(@kuctj< z#_oDP{^ixh4mu_^FsJF^25p%&p5>vw)~EY2p}~GG273w#e%~+WSoZS!XSI?os2)`B(MUPtnT$N|D>!oZmj1SsFyIw$#45a`WRa z(lBQalK%9t^Wdj9X!Ck@qao&U&Jt9=F5N5mb^hoR>~ST2;-Jmz**aUILu**-*Nc2@ zfew5ieyx?fRwFifIiyz)g@=6jQ*L4w>1omC +#include +#include "qt_iconindicators.hpp" + +QIcon +getIndicatorIcon(IconIndicator indicator) +{ + switch (indicator) { + case Active: + return QIcon(":/settings/qt/icons/active.ico"); + case Disabled: + return QIcon(":/settings/qt/icons/disabled.ico"); + default: + return QIcon(); + } +} + +QPixmap +getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator) +{ + auto iconPixmap = icon.pixmap(size, iconMode); + + if (indicator == None) + return iconPixmap; + + auto painter = QPainter(&iconPixmap); + auto indicatorPixmap = getIndicatorIcon(indicator).pixmap(size); + + painter.drawPixmap(0, 0, indicatorPixmap); + painter.end(); + + return iconPixmap; +} \ No newline at end of file diff --git a/src/qt/qt_iconindicators.hpp b/src/qt/qt_iconindicators.hpp new file mode 100644 index 000000000..553520063 --- /dev/null +++ b/src/qt/qt_iconindicators.hpp @@ -0,0 +1,15 @@ +#ifndef QT_ICONINDICATORS_HPP +# define QT_INDICATORS_HPP + +#include +#include + +enum IconIndicator { + None, + Active, + Disabled, +}; + +QPixmap getIconWithIndicator(const QIcon &icon, const QSize &size, QIcon::Mode iconMode, IconIndicator indicator); + +#endif \ No newline at end of file diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index eff29a232..d555be360 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -54,6 +54,7 @@ extern "C" { #include "qt_mainwindow.hpp" #include "qt_soundgain.hpp" #include "qt_progsettings.hpp" +#include "qt_iconindicators.hpp" #include @@ -65,19 +66,24 @@ namespace { struct PixmapSetActive { QPixmap normal; QPixmap active; - void load(const QString &basePath); + void load(const QIcon &icon); +}; +struct PixmapSetDisabled { + QPixmap normal; + QPixmap disabled; + void load(const QIcon &icon); }; struct PixmapSetEmpty { QPixmap normal; QPixmap empty; - void load(const QString &basePath); + void load(const QIcon &icon); }; struct PixmapSetEmptyActive { QPixmap normal; QPixmap active; QPixmap empty; QPixmap empty_active; - void load(QString basePath); + void load(const QIcon &icon); }; struct Pixmaps { PixmapSetEmpty cartridge; @@ -90,7 +96,7 @@ struct Pixmaps { PixmapSetEmptyActive mo; PixmapSetActive hd; PixmapSetEmptyActive net; - QPixmap sound, soundMuted; + PixmapSetDisabled sound; }; struct StateActive { @@ -170,30 +176,35 @@ struct StateEmptyActive { }; static QSize pixmap_size(16, 16); -static const QString pixmap_empty = QStringLiteral("_empty"); -static const QString pixmap_active = QStringLiteral("_active"); -static const QString pixmap_empty_active = QStringLiteral("_empty_active"); + void -PixmapSetEmpty::load(const QString &basePath) +PixmapSetEmpty::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None); } void -PixmapSetActive::load(const QString &basePath) +PixmapSetActive::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); } void -PixmapSetEmptyActive::load(QString basePath) +PixmapSetDisabled::load(const QIcon &icon) { - normal = QIcon(basePath.arg(QStringLiteral(""))).pixmap(pixmap_size); - active = QIcon(basePath.arg(pixmap_active)).pixmap(pixmap_size); - empty = QIcon(basePath.arg(pixmap_empty)).pixmap(pixmap_size); - empty_active = QIcon(basePath.arg(pixmap_empty_active)).pixmap(pixmap_size); + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + disabled = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Disabled); +} + +void +PixmapSetEmptyActive::load(const QIcon &icon) +{ + normal = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, None); + active = getIconWithIndicator(icon, pixmap_size, QIcon::Normal, Active); + empty = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, None); + empty_active = getIconWithIndicator(icon, pixmap_size, QIcon::Disabled, Active); } } @@ -202,21 +213,20 @@ struct MachineStatus::States { States(QObject *parent) { - pixmaps.cartridge.load(":/settings/qt/icons/cartridge%1.ico"); - pixmaps.cassette.load(":/settings/qt/icons/cassette%1.ico"); + pixmaps.cartridge.load(QIcon(":/settings/qt/icons/cartridge.ico")); + pixmaps.cassette.load(QIcon(":/settings/qt/icons/cassette.ico")); pixmaps.floppy_disabled.normal = QIcon(":/settings/qt/icons/floppy_disabled.ico").pixmap(pixmap_size); pixmaps.floppy_disabled.active = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty = pixmaps.floppy_disabled.normal; pixmaps.floppy_disabled.empty_active = pixmaps.floppy_disabled.normal; - pixmaps.floppy_525.load(":/settings/qt/icons/floppy_525%1.ico"); - pixmaps.floppy_35.load(":/settings/qt/icons/floppy_35%1.ico"); - pixmaps.cdrom.load(":/settings/qt/icons/cdrom%1.ico"); - pixmaps.zip.load(":/settings/qt/icons/zip%1.ico"); - pixmaps.mo.load(":/settings/qt/icons/mo%1.ico"); - pixmaps.hd.load(":/settings/qt/icons/hard_disk%1.ico"); - pixmaps.net.load(":/settings/qt/icons/network%1.ico"); - pixmaps.sound = QIcon(":/settings/qt/icons/sound.ico").pixmap(pixmap_size); - pixmaps.soundMuted = QIcon(":/settings/qt/icons/sound_mute.ico").pixmap(pixmap_size); + pixmaps.floppy_525.load(QIcon(":/settings/qt/icons/floppy_525.ico")); + pixmaps.floppy_35.load(QIcon(":/settings/qt/icons/floppy_35.ico")); + pixmaps.cdrom.load(QIcon(":/settings/qt/icons/cdrom.ico")); + pixmaps.zip.load(QIcon(":/settings/qt/icons/zip.ico")); + pixmaps.mo.load(QIcon(":/settings/qt/icons/mo.ico")); + pixmaps.hd.load(QIcon(":/settings/qt/icons/hard_disk.ico")); + pixmaps.net.load(QIcon(":/settings/qt/icons/network.ico")); + pixmaps.sound.load(QIcon(":/settings/qt/icons/sound.ico")); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -510,7 +520,7 @@ MachineStatus::refresh(QStatusBar *sbar) sound_muted ^= 1; config_save(); if (d->sound) - d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); }); @@ -694,7 +704,7 @@ MachineStatus::refresh(QStatusBar *sbar) } d->sound = std::make_unique(); - d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + d->sound->setPixmap(sound_muted ? d->pixmaps.sound.disabled : d->pixmaps.sound.normal); if (muteUnmuteAction) muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 6ca323b89..dc8db2c06 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -1,16 +1,9 @@ qt/icons/cartridge.ico - qt/icons/cartridge_empty.ico qt/icons/cassette.ico - qt/icons/cassette_active.ico - qt/icons/cassette_empty.ico - qt/icons/cassette_empty_active.ico qt/icons/cdrom.ico - qt/icons/cdrom_active.ico qt/icons/cdrom_disabled.ico - qt/icons/cdrom_empty.ico - qt/icons/cdrom_empty_active.ico qt/icons/cdrom_mute.ico qt/icons/cdrom_unmute.ico qt/icons/cdrom_image.ico @@ -18,38 +11,24 @@ qt/icons/cdrom_host.ico qt/icons/display.ico qt/icons/floppy_35.ico - qt/icons/floppy_35_active.ico - qt/icons/floppy_35_empty.ico - qt/icons/floppy_35_empty_active.ico qt/icons/floppy_525.ico - qt/icons/floppy_525_active.ico - qt/icons/floppy_525_empty.ico - qt/icons/floppy_525_empty_active.ico qt/icons/floppy_and_cdrom_drives.ico qt/icons/floppy_disabled.ico qt/icons/hard_disk.ico - qt/icons/hard_disk_active.ico qt/icons/input_devices.ico qt/icons/machine.ico qt/icons/mo.ico - qt/icons/mo_active.ico qt/icons/mo_disabled.ico - qt/icons/mo_empty.ico - qt/icons/mo_empty_active.ico qt/icons/network.ico - qt/icons/network_active.ico - qt/icons/network_empty.ico qt/icons/other_peripherals.ico qt/icons/other_removable_devices.ico qt/icons/ports.ico qt/icons/sound.ico - qt/icons/sound_mute.ico qt/icons/storage_controllers.ico qt/icons/zip.ico - qt/icons/zip_active.ico qt/icons/zip_disabled.ico - qt/icons/zip_empty.ico - qt/icons/zip_empty_active.ico + qt/icons/active.ico + qt/icons/disabled.ico qt/icons/86Box-gray.ico qt/icons/86Box-green.ico qt/icons/86Box-red.ico From fcd6bd9c664564eb2e0d03086cafb46e6163d585 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 01:22:35 +0100 Subject: [PATCH 153/158] Serial: Give the OKI IF386AX 16450 serial ports instead of 8250. --- src/device/serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/device/serial.c b/src/device/serial.c index deb97225a..8483f7fe3 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -999,7 +999,8 @@ void serial_standalone_init(void) { while (next_inst < SERIAL_MAX) - device_add_inst(&ns8250_device, next_inst + 1); + device_add_inst(!strcmp(machine_get_internal_name(), "if386sx") ? &ns16450_device : + &ns8250_device, next_inst + 1); }; const device_t ns8250_device = { From 2ed64c83996e762eb10c296666d759068c8ec69f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 08:11:04 +0100 Subject: [PATCH 154/158] Machine settings: Reduce the two loops to determine present machine types to a single loop, reduces the number of iterations from (number of machine types * number of machines) to just (number of machines), speeding things up. --- src/qt/qt_settingsmachine.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 9b1f9849e..34968b288 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -88,20 +88,31 @@ SettingsMachine::SettingsMachine(QWidget *parent) ui->comboBoxPitMode->setCurrentIndex(-1); ui->comboBoxPitMode->setCurrentIndex(pit_mode + 1); - int selectedMachineType = 0; - auto *machineTypesModel = ui->comboBoxMachineType->model(); - for (int i = 1; i < MACHINE_TYPE_MAX; ++i) { - int j = 0; - while (machine_get_internal_name_ex(j) != nullptr) { - if (machine_available(j) && (machine_get_type(j) == i)) { + int selectedMachineType = 0; + auto * machineTypesModel = ui->comboBoxMachineType->model(); + int i = -1; + int j = 0; + int cur_j = 0; + const void *miname; + do { + miname = machine_get_internal_name_ex(j); + + if ((miname == nullptr) || (machine_get_type(j) != i)) { + if ((i != -1) && (cur_j != 0)) { int row = Models::AddEntry(machineTypesModel, machine_types[i].name, machine_types[i].id); if (machine_types[i].id == machine_get_type(machine)) selectedMachineType = row; - break; } - j++; + + i = machine_get_type(j); + cur_j = 0; } - } + + if (machine_available(j)) + cur_j++; + + j++; + } while (miname != nullptr); ui->comboBoxMachineType->setCurrentIndex(-1); ui->comboBoxMachineType->setCurrentIndex(selectedMachineType); From bb22e1dccb39b0ce1af9bfbb3202c5a78da3bdb3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 29 Mar 2025 08:14:30 +0100 Subject: [PATCH 155/158] Moved the Packard Bell PB450 to the correct place on the machines list. --- src/machine/machine_table.c | 80 ++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index aa9bae305..fa383139b 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6981,46 +6981,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ - { - .name = "[OPTi 895] Packard Bell PB450", - .internal_name = "pb450", - .type = MACHINE_TYPE_486_S3_PCI, - .chipset = MACHINE_CHIPSET_OPTI_895_802G, - .init = machine_at_pb450_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_PS2_PCI, - .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, - .ram = { - .min = 1024, - .max = 65536, - .step = 1024 - }, - .nvrmask = 255, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = &pb450_device, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = &gd5428_vlb_onboard_device, - .snd_device = NULL, - .net_device = NULL - }, /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ { .name = "[SiS 461] Acer V10", @@ -7915,6 +7875,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */ + { + .name = "[OPTi 895] Packard Bell PB450", + .internal_name = "pb450", + .type = MACHINE_TYPE_486_S3_PCI, + .chipset = MACHINE_CHIPSET_OPTI_895_802G, + .init = machine_at_pb450_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_PS2_PCI, + .flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = &pb450_device, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5428_vlb_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* This has an AMIKey-2, which is an updated version of type 'H'. */ { .name = "[i420EX] ASUS PVI-486AP4", From 6d43f7e2df212fd7d9bf662a0fcf6caa18c75541 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:24:20 +0100 Subject: [PATCH 156/158] More fixes for 5380-based SCSI chips of the day (March 29th, 2025) 1. Avoid audio stops when they don't need to be. 2. And improved the MMIO-based NCR 53c400 timings to be similar to the port I/O-based one (T130B). 3. Minor timing fixes to the T128/PAS as well (especially for the hdd, when entering Windows 1.x using a SCSI HDD). --- src/scsi/scsi_ncr5380.c | 3 -- src/scsi/scsi_ncr53c400.c | 94 ++++++++++++++++++++++++++++----------- src/scsi/scsi_t128.c | 15 ++++--- 3 files changed, 77 insertions(+), 35 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 048194a96..132fade37 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -95,9 +95,6 @@ ncr5380_reset(ncr_t *ncr) ncr->timer(ncr->priv, 0.0); - for (int i = 0; i < 8; i++) - scsi_device_reset(&scsi_devices[ncr->bus][i]); - scsi_bus->state = STATE_IDLE; scsi_bus->clear_req = 0; scsi_bus->wait_complete = 0; diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index fc62a1cab..f91dc83a9 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -29,11 +29,11 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> -#include <86box/timer.h> #include <86box/dma.h> #include <86box/pic.h> #include <86box/mca.h> #include <86box/mem.h> +#include <86box/timer.h> #include <86box/rom.h> #include <86box/device.h> #include <86box/nvr.h> @@ -41,6 +41,7 @@ #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/scsi_ncr5380.h> +#include "cpu.h" #define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" #define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin" @@ -80,6 +81,7 @@ typedef struct ncr53c400_t { int buffer_host_pos; int busy; + int reset; uint8_t pos_regs[8]; pc_timer_t timer; @@ -126,6 +128,9 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) addr &= 0x3fff; + if (addr >= 0x3880) + ncr53c400_log("%04X:%08X: memio_write(%04x)=%02x\n", CS, cpu_state.pc, addr, val); + if (addr >= 0x3a00) ncr400->ext_ram[addr - 0x3a00] = val; else { @@ -147,6 +152,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr400->busy = 1; + if (ncr400->type != ROM_T130B) + timer_on_auto(&ncr400->timer, 1.0); } } else ncr53c400_log("No Write.\n"); @@ -155,6 +162,19 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) case 0x3980: switch (addr) { case 0x3980: /* Control */ + /*Parity bits*/ + /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/ + /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/ + /*Required by RTASPI10.SYS otherwise it won't initialize.*/ + if (val & 0x80) { + if (ncr->mode & 0x30) { + if (!(ncr->mode & MODE_DMA)) { + ncr->mode = 0x00; + ncr400->reset = 1; + } + } + } + ncr53c400_log("NCR 53c400 control=%02x, mode=%02x.\n", val, ncr->mode); if ((val & CTRL_DATA_DIR) && !(ncr400->status_ctrl & CTRL_DATA_DIR)) { ncr400->buffer_host_pos = MIN(128, dev->buffer_length); @@ -180,10 +200,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) } if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); - if (ncr400->type == ROM_T130B) - timer_on_auto(&ncr400->timer, 10.0); - else - timer_on_auto(&ncr400->timer, scsi_bus->period); + timer_on_auto(&ncr400->timer, 10.0); ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, p=%lf enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, scsi_bus->wait_data, scsi_bus->wait_complete, scsi_bus->clear_req, scsi_bus->period, timer_is_enabled(&ncr400->timer)); } else @@ -241,6 +258,20 @@ ncr53c400_read(uint32_t addr, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; + if (ncr400->type != ROM_T130B) { + if (!ncr400->block_count_loaded) { + scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } else if (!timer_is_enabled(&ncr400->timer)) { + ncr53c400_log("Timer re-enabled.\n"); + timer_on_auto(&ncr400->timer, 1.0); + } + } } } break; @@ -252,11 +283,10 @@ ncr53c400_read(uint32_t addr, void *priv) ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY); if (!ncr400->busy) ret |= STATUS_5380_ACCESSIBLE; - if (ncr->mode & 0x30) { /*Parity bits*/ - if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/ - ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/ - ncr->mode = 0x00; /*Required by RTASPI10.SYS otherwise it won't initialize.*/ - } + + if (ncr400->reset) { + ncr400->reset = 0; + ret |= 0x01; } ncr53c400_log("NCR 53c400 status=%02x.\n", ret); break; @@ -267,7 +297,10 @@ ncr53c400_read(uint32_t addr, void *priv) break; case 0x3982: /* switch register read */ - ret = 0xff; + if (ncr->irq != -1) { + ret = 0xf8; + ret += ncr->irq; + } ncr53c400_log("Switches read=%02x.\n", ret); break; @@ -282,7 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv) } if (addr >= 0x3880) - ncr53c400_log("memio_read(%08x)=%02x\n", addr, ret); + ncr53c400_log("%04X:%08X: memio_read(%04x)=%02x\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -424,11 +457,8 @@ ncr53c400_callback(void *priv) uint8_t status; if (scsi_bus->tx_mode != PIO_TX_BUS) { - if (ncr400->type == ROM_T130B) { - ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0); - timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0); - } else - timer_on_auto(&ncr400->timer, 1.0); + ncr53c400_log("PERIOD T130B DMA=%lf.\n", scsi_bus->period / 225.0); + timer_on_auto(&ncr400->timer, scsi_bus->period / 225.0); } if (scsi_bus->data_wait & 1) { @@ -538,14 +568,17 @@ ncr53c400_callback(void *priv) ncr400->block_count = (ncr400->block_count - 1) & 0xff; ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count); if (!ncr400->block_count) { - scsi_bus->tx_mode = PIO_TX_BUS; ncr400->block_count_loaded = 0; - ncr53c400_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr53c400_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); - } + if (ncr400->type == ROM_T130B) { + scsi_bus->tx_mode = PIO_TX_BUS; + ncr53c400_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr53c400_log("NCR read irq\n"); + ncr5380_irq(ncr, 1); + } + } else + timer_on_auto(&ncr400->timer, 1.0); } break; } @@ -732,8 +765,17 @@ ncr53c400_init(const device_t *info) scsi_bus_set_speed(ncr->bus, 5000000.0); scsi_bus->speed = 0.2; - scsi_bus->divider = 2.0; - scsi_bus->multi = 1.750; + if (ncr400->type == ROM_T130B) { + scsi_bus->divider = 2.0; + scsi_bus->multi = 1.750; + } else { + scsi_bus->divider = 1.0; + scsi_bus->multi = 1.0; + } + + for (int i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[ncr->bus][i]); + return ncr400; } diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index eada27246..3f273d1bb 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -95,9 +95,10 @@ t128_write(uint32_t addr, uint8_t val, void *priv) t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded); t128->status &= ~0x04; - timer_on_auto(&t128->timer, 10.0); + timer_on_auto(&t128->timer, 1.0); } - } + } else + t128_log("Write not allowed.\n"); } } @@ -136,20 +137,18 @@ t128_read(uint32_t addr, void *priv) t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + t128->status &= ~0x04; if (!t128->block_loaded) { ncr->isr |= STATUS_END_OF_DMA; if (ncr->mode & MODE_ENA_EOP_INT) { t128_log("T128 read irq\n"); ncr5380_irq(ncr, 1); } - t128->status &= ~0x04; scsi_bus->bus_out |= BUS_CD; scsi_bus->tx_mode = PIO_TX_BUS; timer_stop(&t128->timer); } else if (!timer_is_enabled(&t128->timer)) - timer_on_auto(&t128->timer, 10.0); - else - t128->status &= ~0x04; + timer_on_auto(&t128->timer, 1.0); } } else { /*According to the WinNT DDK sources, just get the status timeout bit from here.*/ @@ -522,6 +521,10 @@ t128_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 1.0; scsi_bus->multi = 1.0; + + for (int i = 0; i < 8; i++) + scsi_device_reset(&scsi_devices[ncr->bus][i]); + return t128; } From c91f2255ad7795573ab2383e2a3205df69d308ad Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:42:25 +0100 Subject: [PATCH 157/158] Vast overhaul for the Mach8/32/8514/A (March 29th, 2025) 1. Implemented the FIFO test data to pass some tests of the Mach8 POST ROM and tests (not complete yet). 2. Overhauled the mode switches again, but this time with way less hacks and more on manual instructions. 3. Use a function pointer to determine if the Mach8 type used is a VGA combo or add-on. 4. Mach32 mode tests are no longer incorrectly green (was caused by improper pixtrans parts). 5. Implemented overscan color to the Mach32 as well as the CRT offset. 6. And fixed a PCI LFB GPF issue with the Mach32 2.3 drivers on Win3.1x. 7. Implemented memory boundary for both the Mach32 SVGA and its accelerator. 8. Added undocumented ports used by the FIFO (such as ports 0x8AEE and 0xEAEE). 9. Plus resetting the device right a la s3. 10. Temporarily switched the bus type of the Mach8 to 8-bit in both MCA and ISA variants. --- src/include/86box/vid_8514a.h | 21 +- src/include/86box/vid_ati_mach8.h | 14 +- src/video/vid_8514a.c | 696 +++++---- src/video/vid_ati_mach8.c | 2381 +++++++++++++++++++---------- 4 files changed, 1939 insertions(+), 1173 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index bfde22d5e..153bface4 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -18,6 +18,12 @@ #ifndef VIDEO_8514A_H #define VIDEO_8514A_H +#define INT_VSY (1 << 0) +#define INT_GE_BSY (1 << 1) +#define INT_FIFO_OVR (1 << 2) +#define INT_FIFO_EMP (1 << 3) +#define INT_MASK 0xf + typedef struct hwcursor8514_t { int ena; int x; @@ -61,6 +67,7 @@ typedef struct ibm8514_t { uint32_t vram_mask; uint32_t pallook[512]; uint32_t bios_addr; + uint32_t ma_latch; PALETTE vgapal; uint8_t hwcursor_oddeven; @@ -85,8 +92,8 @@ typedef struct ibm8514_t { uint16_t advfunc_cntl; uint16_t cur_y; uint16_t cur_x; - int16_t destx; - int16_t desty; + uint16_t destx; + uint16_t desty; int16_t desty_axstp; int16_t destx_distp; int16_t err_term; @@ -117,6 +124,8 @@ typedef struct ibm8514_t { int y1; int y2; int temp_cnt; + int16_t dx_ibm; + int16_t dy_ibm; int16_t cx; int16_t cx_back; int16_t cy; @@ -216,10 +225,9 @@ typedef struct ibm8514_t { uint16_t subsys_cntl; uint8_t subsys_stat; - atomic_int fifo_idx; - atomic_int ext_fifo_idx; atomic_int force_busy; atomic_int force_busy2; + atomic_int fifo_idx; int blitter_busy; uint64_t blitter_time; @@ -235,6 +243,11 @@ typedef struct ibm8514_t { PALETTE _8514pal; latch8514_t latch; + + void (*vblank_start)(void *priv); + void (*accel_out_fifo)(void *priv, uint16_t port, uint16_t val, int len); + void (*update_irqs)(void *priv); + } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index 849446def..4a5d3deb5 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -25,6 +25,7 @@ typedef struct mach_t { rom_t bios_rom; rom_t bios_rom2; mem_mapping_t mmio_linear_mapping; + mem_mapping_t banked_mapping; int mca_bus; int pci_bus; @@ -71,7 +72,12 @@ typedef struct mach_t { uint8_t bank_r; uint16_t shadow_set; uint16_t shadow_cntl; - int override_resolution; + uint8_t overscan_col_8; + uint8_t overscan_b_col_24; + uint8_t overscan_g_col_24; + uint8_t overscan_r_col_24; + uint16_t fifo_test_data[17]; + int resolution_crt; struct { uint8_t line_idx; @@ -79,9 +85,9 @@ typedef struct mach_t { uint8_t patt_idx; uint8_t patt_len; uint8_t pix_trans[2]; - uint8_t eeprom_control; uint8_t alu_bg_fn; uint8_t alu_fg_fn; + uint16_t eeprom_control; uint16_t clip_left; uint16_t clip_right; uint16_t clip_top; @@ -92,6 +98,7 @@ typedef struct mach_t { uint16_t src_x_end; uint16_t src_x_start; uint16_t src_x; + uint16_t r_src_x; uint16_t src_y; int16_t bres_count; uint16_t clock_sel; @@ -100,6 +107,8 @@ typedef struct mach_t { uint16_t dest_cmp_fn; uint16_t dp_config; uint16_t ext_ge_config; + uint16_t crt_offset_lo; + uint16_t crt_offset_hi; uint16_t ge_offset_lo; uint16_t ge_offset_hi; uint16_t linedraw_opt; @@ -159,6 +168,7 @@ typedef struct mach_t { } accel; atomic_int force_busy; + atomic_int fifo_test_idx; } mach_t; #endif /*VIDEO_ATI_MACH8_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 765258237..efb05a307 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -15,6 +15,7 @@ * * Copyright 2022-2024 TheCollector1995. */ +#include #include #include #include @@ -32,7 +33,6 @@ #include <86box/mca.h> #include <86box/rom.h> #include <86box/plat.h> -#include <86box/thread.h> #include <86box/video.h> #include <86box/vid_8514a.h> #include <86box/vid_8514a_device.h> @@ -153,12 +153,15 @@ CLAMP(int16_t in, int16_t min, int16_t max) dest_dat = ~(src_dat & dest_dat); \ break; \ case 0x09: \ + case 0x11: \ dest_dat = ~src_dat | dest_dat; \ break; \ case 0x0a: \ + case 0x12: \ dest_dat = src_dat | ~dest_dat; \ break; \ case 0x0b: \ + case 0x13: \ dest_dat = src_dat | dest_dat; \ break; \ case 0x0c: \ @@ -176,56 +179,43 @@ CLAMP(int16_t in, int16_t min, int16_t max) case 0x10: \ dest_dat = MIN(src_dat, dest_dat); \ break; \ - case 0x11: \ - dest_dat = dest_dat - src_dat; \ - break; \ - case 0x12: \ - dest_dat = src_dat - dest_dat; \ - break; \ - case 0x13: \ - dest_dat = src_dat + dest_dat; \ - break; \ case 0x14: \ dest_dat = MAX(src_dat, dest_dat); \ break; \ case 0x15: \ - dest_dat = (dest_dat - src_dat) >> 1; \ + dest_dat = (src_dat | ~dest_dat) >> 1; \ break; \ case 0x16: \ - dest_dat = (src_dat - dest_dat) >> 1; \ + dest_dat = (~src_dat | dest_dat) >> 1; \ break; \ case 0x17: \ - dest_dat = (dest_dat + src_dat) >> 1; \ + dest_dat = (src_dat | dest_dat) >> 1; \ break; \ case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ + dest_dat = MAX(0, ~src_dat | dest_dat); \ break; \ case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ + dest_dat = MAX(0, src_dat | ~dest_dat); \ break; \ case 0x1b: \ if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xffff, src_dat | dest_dat); \ else \ - dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xff, src_dat | dest_dat); \ break; \ case 0x1c: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ - break; \ case 0x1d: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + dest_dat = MAX(0, ~src_dat | dest_dat) >> 1; \ break; \ case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + dest_dat = MAX(0, src_dat | ~dest_dat) >> 1; \ break; \ case 0x1f: \ if (dev->bpp) \ - dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xffff < (src_dat | dest_dat)) ? 0xffff : ((src_dat | dest_dat) >> 1); \ else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xff < (src_dat | dest_dat)) ? 0xff : ((src_dat | dest_dat) >> 1); \ break; \ } \ } @@ -233,10 +223,10 @@ CLAMP(int16_t in, int16_t min, int16_t max) #define WRITE(addr, dat) \ if (dev->bpp) { \ vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else { \ dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ } int ibm8514_active = 0; @@ -246,7 +236,7 @@ ibm8514_cpu_src(svga_t *svga) { const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (!(dev->accel.cmd & 0x100)) + if (dev->accel.cmd_back) return 0; if (dev->accel.cmd & 1) @@ -260,7 +250,7 @@ ibm8514_cpu_dest(svga_t *svga) { const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (!(dev->accel.cmd & 0x100)) + if (dev->accel.cmd_back) return 0; if (dev->accel.cmd & 1) @@ -282,7 +272,7 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in int bkgd_mix = (dev->accel.bkgd_mix >> 5) & 3; int cmd = dev->accel.cmd >> 13; - if (dev->accel.cmd & 0x100) { + if (!dev->accel.cmd_back) { if (len == 2) { /*Bus size*/ if (dev->accel.cmd & 0x200) /*16-bit*/ @@ -344,27 +334,184 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port != 0x9ae8 && port != 0xe2e8) - ibm8514_log("Port OUT FIFO=%04x, val=%04x, len=%d.\n", port, val, len); - switch (port) { + case 0x2e8: + WRITE8(port, dev->htotal, val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0x6e8: + /*In preparation to switch from VGA to 8514/A mode*/ + WRITE8(port, dev->hdisped, val); + dev->hdisp = (dev->hdisped + 1) << 3; + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + svga_recalctimings(svga); + break; + + case 0x6e9: + WRITE8(port, dev->htotal, val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0xae8: + WRITE8(port, dev->hsync_start, val); + pclog("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_start=%d.\n", port, val, (val + 1) << 3); + svga_recalctimings(svga); + break; + + case 0xee8: + WRITE8(port, dev->hsync_width, val); + pclog("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); + svga_recalctimings(svga); + break; + + case 0x12e8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_total_reg = val; + dev->v_total_reg &= 0x1fff; + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_total_reg, val); + } + break; + case 0x12e9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x16e8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_disp = val; + dev->v_disp &= 0x1fff; + dev->vdisp = (dev->v_disp + 1) >> 1; + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_disp, val); + } + break; + case 0x16e9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + dev->vdisp = (dev->v_disp + 1) >> 1; + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x1ae8: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 2) { + dev->v_sync_start = val; + dev->v_sync_start &= 0x1fff; + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); + svga_recalctimings(svga); + } else { + WRITE8(port, dev->v_sync_start, val); + } + break; + case 0x1ae9: + /*In preparation to switch from VGA to 8514/A mode*/ + if (len == 1) { + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); + svga_recalctimings(svga); + } + break; + + case 0x22e8: + dev->disp_cntl = val; + dev->interlace = !!(dev->disp_cntl & 0x10); + ibm8514_log("IBM 8514/A compatible: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); + svga_recalctimings(svga); + break; + + case 0x1ee8: + case 0x1ee9: + ibm8514_log("IBM 8514/A compatible: V_SYNC_WID write 1EE8 = %02x\n", val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncwidth=0x%02x.\n", port, val); + svga_recalctimings(svga); + break; + + case 0x42e8: + ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + if (len == 2) { + dev->subsys_cntl = val; + dev->subsys_stat &= ~val; + if ((val & 0xc000) == 0x8000) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } + } else { + WRITE8(port, dev->subsys_cntl, val); + dev->subsys_stat &= ~val; + } + break; + case 0x42e9: + if (len == 1) { + WRITE8(port, dev->subsys_cntl, val); + if ((val & 0xc0) == 0x80) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } + } + break; + + case 0x4ae8: + WRITE8(port, dev->accel.advfunc_cntl, val); + dev->on = dev->accel.advfunc_cntl & 0x01; + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + ibm8514_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); + svga_recalctimings(svga); + break; + case 0x82e8: case 0xc2e8: - dev->fifo_idx++; if (len == 2) dev->accel.cur_y = val & 0x7ff; break; case 0x86e8: case 0xc6e8: - dev->fifo_idx++; if (len == 2) dev->accel.cur_x = val & 0x7ff; break; case 0x8ae8: case 0xcae8: - dev->fifo_idx++; if (len == 2) { dev->accel.desty = val & 0x7ff; dev->accel.desty_axstp = val & 0x3fff; @@ -375,7 +522,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x8ee8: case 0xcee8: - dev->fifo_idx++; if (len == 2) { dev->accel.destx = val & 0x7ff; dev->accel.destx_distp = val & 0x3fff; @@ -385,7 +531,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x92e8: - dev->fifo_idx++; if (len == 2) dev->test = val; fallthrough; @@ -400,7 +545,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x96e8: case 0xd6e8: - dev->fifo_idx++; if (len == 2) { dev->accel.maj_axis_pcnt = val & 0x7ff; dev->accel.maj_axis_pcnt_no_limit = val; @@ -409,7 +553,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0x9ae8: case 0xdae8: - dev->fifo_idx++; dev->accel.ssv_state = 0; if (len == 2) { dev->data_available = 0; @@ -419,14 +562,13 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; - ibm8514_log("8514/A CMD=%04x, back=%d.\n", dev->accel.cmd, dev->accel.cmd_back); + ibm8514_log("8514/A CMD=%04x, back=%d, frgd color=%04x, frgdmix=%02x, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.cmd_back, dev->accel.frgd_color, dev->accel.frgd_mix, dev->accel.multifunc[0x0a]); ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; case 0x9ee8: case 0xdee8: - dev->fifo_idx++; dev->accel.ssv_state = 1; if (len == 2) { dev->accel.short_stroke = val; @@ -451,7 +593,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xa2e8: case 0xe2e8: - dev->fifo_idx++; if (port == 0xe2e8) { if (len == 2) { if (dev->accel.cmd_back) @@ -470,7 +611,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xa6e8: case 0xe6e8: - dev->fifo_idx++; if (port == 0xe6e8) { if (len == 2) { if (dev->accel.cmd_back) @@ -489,40 +629,34 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) case 0xaae8: case 0xeae8: - dev->fifo_idx++; if (len == 2) dev->accel.wrt_mask = val; break; case 0xaee8: case 0xeee8: - dev->fifo_idx++; if (len == 2) dev->accel.rd_mask = val; break; case 0xb2e8: case 0xf2e8: - dev->fifo_idx++; if (len == 2) dev->accel.color_cmp = val; break; case 0xb6e8: case 0xf6e8: - dev->fifo_idx++; dev->accel.bkgd_mix = val & 0xff; break; case 0xbae8: case 0xfae8: - dev->fifo_idx++; dev->accel.frgd_mix = val & 0xff; break; case 0xbee8: case 0xfee8: - dev->fifo_idx++; if (len == 2) { dev->accel.multifunc_cntl = val; dev->accel.multifunc[dev->accel.multifunc_cntl >> 12] = dev->accel.multifunc_cntl & 0xfff; @@ -631,115 +765,13 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - ibm8514_accel_out_fifo(svga, port, val, len); - else { - switch (port) { - case 0x2e8: - case 0x6e9: - WRITE8(port, dev->htotal, val); - ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x6e8: - /*In preparation to switch from VGA to 8514/A mode*/ - dev->hdisped = val; - dev->hdisp = (dev->hdisped + 1) << 3; - ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); - svga_recalctimings(svga); - break; - - case 0xae8: - dev->hsync_start = val; - ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_start=%d.\n", port, val, (val + 1) << 3); - svga_recalctimings(svga); - break; - - case 0xee8: - dev->hsync_width = val; - ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); - svga_recalctimings(svga); - break; - - case 0x12e8: - case 0x12e9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; - dev->v_total = dev->v_total_reg + 1; - if (dev->interlace) - dev->v_total >>= 1; - - ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x16e8: - case 0x16e9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_disp, val); - dev->v_disp &= 0x1fff; - dev->vdisp = (dev->v_disp + 1) >> 1; - ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); - ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ae8: - case 0x1ae9: - /*In preparation to switch from VGA to 8514/A mode*/ - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - dev->v_syncstart = dev->v_sync_start + 1; - if (dev->interlace) - dev->v_syncstart >>= 1; - - ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); - ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ee8: - case 0x1ee9: - ibm8514_log("IBM 8514/A compatible: V_SYNC_WID write 1EE8 = %02x\n", val); - ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncwidth=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x22e8: - dev->disp_cntl = val; - dev->interlace = !!(dev->disp_cntl & 0x10); - ibm8514_log("IBM 8514/A compatible: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); - svga_recalctimings(svga); - break; - - case 0x42e8: - ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); - dev->subsys_cntl = (dev->subsys_cntl & 0xff00) | val; - dev->subsys_stat &= ~val; - break; - case 0x42e9: - dev->subsys_cntl = (dev->subsys_cntl & 0xff) | (val << 8); - if ((val & 0xc0) == 0x80) { - dev->fifo_idx = 0; - dev->force_busy = 0; - dev->force_busy2 = 0; - } - break; - - case 0x4ae8: - WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on = dev->accel.advfunc_cntl & 0x01; - ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); - ibm8514_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); - svga_recalctimings(svga); - break; - - default: - break; - } + if (dev->accel.cmd_back) { + dev->fifo_idx++; + if (dev->fifo_idx > 8) + dev->fifo_idx = 8; } + + ibm8514_accel_out_fifo(svga, port, val, len); } static void @@ -790,28 +822,21 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) case 0x9ae8: case 0xdae8: - if ((dev->fifo_idx >= 1) && (dev->fifo_idx <= 8)) { - temp |= (1 << (dev->fifo_idx - 1)); - switch (dev->accel.cmd >> 13) { - case 2: - case 3: - case 4: - case 6: - if (dev->accel.sy < 0) - dev->fifo_idx = 0; - break; - default: - if (!dev->accel.sy) - dev->fifo_idx = 0; - break; - } - } if (len == 2) { + if (dev->fifo_idx <= 8) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (7 - (i - 1))); + } else + temp = 0x00ff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; + if (dev->force_busy) - temp |= 0x200; /*Hardware busy*/ + temp |= 0x0200; /*Hardware busy*/ dev->force_busy = 0; if (dev->data_available) { - temp |= 0x100; /*Read Data available*/ + temp |= 0x0100; /*Read Data available*/ dev->data_available = 0; } } @@ -819,8 +844,11 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) case 0x9ae9: case 0xdae9: if (len == 1) { + dev->fifo_idx = 0; + if (dev->force_busy2) temp |= 0x02; /*Hardware busy*/ + dev->force_busy2 = 0; if (dev->data_available2) { temp |= 0x01; /*Read Data available*/ @@ -868,7 +896,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) switch (port) { case 0x2e8: - if (dev->vc == dev->dispend) + if (dev->vc == dev->v_syncstart) temp |= 0x02; ibm8514_log("Read: Display Status1=%02x.\n", temp); @@ -896,36 +924,35 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) case 0x42e8: case 0x42e9: - if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) - temp |= 0x01; + if (!(port & 1)) { + if ((dev->subsys_cntl & INT_VSY) && !(dev->subsys_stat & INT_VSY) && (dev->vc == dev->dispend)) + temp |= INT_VSY; - if (cmd == 6) { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r_ibm) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b_ibm)) - temp |= 0x02; - } else { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r_ibm) && - (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b_ibm)) - temp |= 0x02; - } + if (cmd == 6) { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r_ibm) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b_ibm)) + temp |= INT_GE_BSY; + } else { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r_ibm) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b_ibm)) + temp |= INT_GE_BSY; + } - if (!dev->fifo_idx) { - if (!dev->force_busy && !dev->force_busy2) - temp |= 0x08; - } - - if (port & 1) { - temp = dev->vram_512k_8514 ? 0x00 : 0x80; - temp |= (dev->subsys_cntl >> 8); - } else { + if (dev->accel.cmd_back) { + dev->force_busy = 0; + dev->force_busy2 = 0; + dev->data_available = 0; + dev->data_available2 = 0; + temp |= INT_FIFO_EMP; + } temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); temp |= 0x20; } @@ -1024,7 +1051,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat rd_mask_polygon &= 0xff; } - if (dev->accel.cmd & 0x100) { + if (!dev->accel.cmd_back) { dev->force_busy = 1; dev->force_busy2 = 1; } @@ -1129,8 +1156,8 @@ 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); + if (cmd != 0) + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); /*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 @@ -1146,7 +1173,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1197,6 +1224,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.ssv_len) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1242,7 +1270,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1293,6 +1321,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!dev->accel.ssv_len) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1378,7 +1407,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -1468,6 +1497,7 @@ 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; + dev->fifo_idx = 0; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1537,7 +1567,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga)) { READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); } else @@ -1588,6 +1618,7 @@ 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; + dev->fifo_idx = 0; break; } @@ -1629,7 +1660,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -1691,6 +1722,7 @@ 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; + dev->fifo_idx = 0; if (!cpu_input) { dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; @@ -1828,7 +1860,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1970,8 +2002,10 @@ skip_vector_rect_write: dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -1986,7 +2020,7 @@ skip_vector_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { @@ -2129,8 +2163,10 @@ skip_nibble_rect_write: dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2148,7 +2184,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2215,8 +2251,10 @@ skip_nibble_rect_write: dev->accel.sy--; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2231,7 +2269,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2301,6 +2339,7 @@ skip_nibble_rect_write: dev->accel.cur_y = dev->accel.cy; } dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -2313,7 +2352,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2412,6 +2451,7 @@ skip_nibble_rect_write: if (dev->accel.sy < 0) { ibm8514_log(".\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; dev->accel.cur_x = dev->accel.cx; dev->accel.cur_y = dev->accel.cy; return; @@ -2419,13 +2459,13 @@ skip_nibble_rect_write: } } } else { - ibm8514_log("Polygon Draw Type=%02x, CX=%d, CY=%d, SY=%d, CL=%d, CR=%d.\n", dev->accel.multifunc[0x0a] & 0x06, dev->accel.cx, dev->accel.cy, dev->accel.sy, clip_l, clip_r); + ibm8514_log("Polygon Draw Type=%02x, CX=%d, CY=%d, SY=%d, CL=%d, CR=%d, frgdmix=%d, bkgdmix=%d, cmpmode=%02x, pitch=%d.\n", dev->accel.multifunc[0x0a] & 0x06, dev->accel.cx, dev->accel.cy, dev->accel.sy, clip_l, clip_r, frgd_mix, bkgd_mix, compare_mode, dev->pitch); 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)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2501,6 +2541,7 @@ skip_nibble_rect_write: dev->accel.cur_y = dev->accel.cy; } dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -2548,7 +2589,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2603,6 +2644,7 @@ skip_nibble_rect_write: if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -2656,7 +2698,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2707,6 +2749,7 @@ skip_nibble_rect_write: if (!dev->accel.sy) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -2753,13 +2796,8 @@ skip_nibble_rect_write: { dev->accel.x_count = 0; - dev->accel.dx = dev->accel.destx; - if (dev->accel.destx >= 0x600) - dev->accel.dx |= ~0x5ff; - - dev->accel.dy = dev->accel.desty; - if (dev->accel.desty >= 0x600) - dev->accel.dy |= ~0x5ff; + dev->accel.dx_ibm = dev->accel.destx; + dev->accel.dy_ibm = dev->accel.desty; dev->accel.cx = dev->accel.cur_x; if (dev->accel.cur_x >= 0x600) @@ -2774,13 +2812,13 @@ skip_nibble_rect_write: if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.fill_state = 0; @@ -2805,17 +2843,16 @@ skip_nibble_rect_write: dev->data_available = 1; dev->data_available2 = 1; return; /*Wait for data from CPU*/ - } + } else + ibm8514_log("BitBLT normal: Parameters: DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, dstheight=%d, clipl=%d, clipr=%d, clipt=%d, clipb=%d.\n", dev->accel.dx_ibm, dev->accel.dy_ibm, dev->accel.cx, dev->accel.cy, dev->accel.sx, dev->accel.sy, clip_l, clip_r, clip_t, clip_b); } - ibm8514_log("BitBLT: full=%04x, odd=%d, c(%d,%d), d(%d,%d), xcount=%d, and3=%d, len(%d,%d), CURX=%d, Width=%d, pixcntl=%d, mix_dat=%08x, count=%d, cpu_data=%08x, cpu_input=%d.\n", dev->accel.cmd, dev->accel.input, dev->accel.cx, dev->accel.cy, dev->accel.dx, dev->accel.dy, dev->accel.x_count, and3, dev->accel.sx, dev->accel.sy, dev->accel.cur_x, dev->accel.maj_axis_pcnt, pixcntl, mix_dat, count, cpu_dat, cpu_input); if (cpu_input) { while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2879,7 +2916,7 @@ skip_nibble_rect_write: } } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -2895,20 +2932,20 @@ skip_nibble_rect_write: goto skip_nibble_bitblt_write; dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } else { MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } } if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -2935,37 +2972,39 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; dev->accel.x_count = 0; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -2979,11 +3018,10 @@ skip_nibble_bitblt_write: mix_dat >>= 8; dev->accel.temp_cnt = 8; } - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3002,7 +3040,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3014,7 +3052,7 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } @@ -3025,10 +3063,10 @@ skip_nibble_bitblt_write: } if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3037,36 +3075,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; - if (dev->accel.sy < 0) + if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + } return; } } @@ -3077,11 +3117,10 @@ skip_nibble_bitblt_write: dev->accel.temp_cnt = 8; mix_dat = old_mix_dat; } - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3100,7 +3139,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3112,7 +3151,7 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & 0x01, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } @@ -3120,10 +3159,10 @@ skip_nibble_bitblt_write: mix_dat >>= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3132,37 +3171,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx; - dev->accel.desty = dev->accel.dy; + dev->accel.destx = dev->accel.dx_ibm; + dev->accel.desty = dev->accel.dy_ibm; dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -3174,15 +3214,13 @@ skip_nibble_bitblt_write: int64_t dx; cx = (int64_t) dev->accel.cx; - dx = (int64_t) dev->accel.dx; + dx = (int64_t) dev->accel.dx_ibm; while (1) { if ((dx >= (((int64_t)clip_l) * 3)) && (dx <= (((uint64_t)clip_r) * 3)) && - (dev->accel.dy >= (clip_t << 1)) && - (dev->accel.dy <= (clip_b << 1))) { - dev->subsys_stat |= 0x02; - + (dev->accel.dy_ibm >= (clip_t << 1)) && + (dev->accel.dy_ibm <= (clip_b << 1))) { READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); @@ -3195,16 +3233,16 @@ skip_nibble_bitblt_write: dev->accel.sx--; if (dev->accel.sx < 0) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } } else { while (count-- && dev->accel.sy >= 0) { - if ((dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + if ((dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b)) { if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3238,7 +3276,7 @@ skip_nibble_bitblt_write: break; } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx_ibm, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || @@ -3250,12 +3288,14 @@ skip_nibble_bitblt_write: old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (dev->accel.cmd & 0x04) { if (dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); } } else { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + WRITE(dev->accel.dest + dev->accel.dx_ibm, dest_dat); + ibm8514_log("BitBLT DX=%d, DY=%d, data=%02x, old=%02x, src=%02x, frmix=%02x, bkmix=%02x, pixcntl=%d.\n", dev->accel.dx_ibm, dev->accel.dy_ibm, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); } } } @@ -3264,10 +3304,10 @@ skip_nibble_bitblt_write: mix_dat |= 1; if (dev->accel.cmd & 0x20) { - dev->accel.dx++; + dev->accel.dx_ibm++; dev->accel.cx++; } else { - dev->accel.dx--; + dev->accel.dx_ibm--; dev->accel.cx--; } @@ -3277,37 +3317,38 @@ skip_nibble_bitblt_write: dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { - dev->accel.dx -= (dev->accel.sx + 1); + dev->accel.dx_ibm -= (dev->accel.sx + 1); dev->accel.cx -= (dev->accel.sx + 1); } else { - dev->accel.dx += (dev->accel.sx + 1); + dev->accel.dx_ibm += (dev->accel.sx + 1); dev->accel.cx += (dev->accel.sx + 1); } if (dev->accel.cmd & 0x80) { - dev->accel.dy++; + dev->accel.dy_ibm++; dev->accel.cy++; } else { - dev->accel.dy--; + dev->accel.dy_ibm--; dev->accel.cy--; } if ((dev->accel_bpp == 24) || (dev->accel_bpp <= 8)) { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } else if (dev->bpp) { dev->accel.src = (dev->accel.ge_offset << 1) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 1) + (dev->accel.dy_ibm * dev->pitch); } else { dev->accel.src = (dev->accel.ge_offset << 2) + (dev->accel.cy * dev->pitch); - dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy * dev->pitch); + dev->accel.dest = (dev->accel.ge_offset << 2) + (dev->accel.dy_ibm * dev->pitch); } dev->accel.sy--; if (dev->accel.sy < 0) { - dev->accel.destx = dev->accel.dx; - dev->accel.desty = dev->accel.dy; + dev->accel.destx = dev->accel.dx_ibm; + dev->accel.desty = dev->accel.dy_ibm; dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -3334,7 +3375,7 @@ ibm8514_render_blank(svga_t *svga) dev->firstline_draw = dev->displine; dev->lastline_draw = dev->displine; - uint32_t *line_ptr = &svga->monitor->target_buffer->line[dev->displine + svga->y_add][svga->x_add]; + uint32_t *line_ptr = &buffer32->line[dev->displine + svga->y_add][svga->x_add]; uint32_t line_width = (uint32_t)(dev->h_disp) * sizeof(uint32_t); if (dev->h_disp > 0) @@ -3628,7 +3669,7 @@ ibm8514_poll(void *priv) int wx; int wy; - ibm8514_log("IBM 8514/A poll=%x.\n", dev->on); + ibm8514_log("IBM 8514/A poll=%x offtime=%" PRIu64 ", ontime=%" PRIu64 ".\n", dev->on, dev->dispofftime, dev->dispontime); if (dev->on) { ibm8514_log("ON!\n"); if (!dev->linepos) { @@ -3713,7 +3754,7 @@ ibm8514_poll(void *priv) dev->vc &= 0xfff; if (dev->vc == dev->dispend) { - dev->subsys_stat |= 0x01; + dev->vblank_start(svga); ibm8514_log("VBLANK irq.\n"); dev->dispon = 0; @@ -3751,16 +3792,16 @@ ibm8514_poll(void *priv) svga->vslines = 0; if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = (dev->rowoffset << 1); + dev->ma = dev->maback = dev->ma_latch + (dev->rowoffset << 1); else - dev->ma = dev->maback = 0; + dev->ma = dev->maback = dev->ma_latch; dev->ma = (dev->ma << 2); dev->maback = (dev->maback << 2); } if (dev->vc == dev->v_total) { dev->vc = 0; - dev->sc = 0; + dev->sc = (svga->crtc[0x8] & 0x1f); dev->dispon = 1; dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; @@ -3876,6 +3917,15 @@ ibm8514_mca_reset(void *priv) svga_set_poll(svga); } +static void +ibm8514_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->subsys_stat |= INT_VSY; +} + static void * ibm8514_init(const device_t *info) { @@ -3938,6 +3988,7 @@ ibm8514_init(const device_t *info) fallthrough; default: + dev->extensions = 0; ibm8514_io_set(svga); if (dev->type & DEVICE_MCA) { @@ -3945,8 +3996,11 @@ ibm8514_init(const device_t *info) dev->pos_regs[1] = 0xef; mca_add(ibm8514_mca_read, ibm8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); } + + dev->vblank_start = ibm8514_vblank_start; break; } + return svga; } @@ -3981,7 +4035,7 @@ ibm8514_force_redraw(void *priv) { svga_t *svga = (svga_t *) priv; - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; } // clang-format off diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index d35257ea7..9f1bb99d6 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -70,6 +70,10 @@ static uint16_t ati8514_accel_inw(uint16_t port, void *priv); static uint32_t ati8514_accel_inl(uint16_t port, void *priv); static void mach32_updatemapping(mach_t *mach, svga_t *svga); +static __inline void mach32_writew_linear(uint32_t addr, uint16_t val, mach_t *mach); +static __inline void mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach, svga_t *svga); + +static mach_t *reset_state = NULL; #ifdef ENABLE_MACH_LOG int mach_do_log = ENABLE_MACH_LOG; @@ -121,14 +125,14 @@ mach_log(const char *fmt, ...) } #define READ_PIXTRANS_WORD(cx, n) \ - if ((cmd == 0) || (cmd == 1) || (cmd == 5) || (mach->accel.cmd_type == -1)) { \ + if ((cmd == 0) || (cmd == 1) || (cmd == 5) || ((mach->accel.cmd_type == -1) && (cmd != 2))) { \ if (dev->bpp) \ temp = vram_w[((dev->accel.cy * dev->pitch) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ else { \ temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } \ - } else if ((mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ + } else if (((cmd == 2) && (mach->accel.cmd_type == -1)) || (mach->accel.cmd_type == 2) || (mach->accel.cmd_type == 5)) { \ if (dev->bpp) \ temp = vram_w[((dev->accel.dest) + (cx) + (n)) & (dev->vram_mask >> 1)]; \ else { \ @@ -184,12 +188,15 @@ mach_log(const char *fmt, ...) dest_dat = ~(src_dat & dest_dat); \ break; \ case 0x09: \ + case 0x11: \ dest_dat = ~src_dat | dest_dat; \ break; \ case 0x0a: \ + case 0x12: \ dest_dat = src_dat | ~dest_dat; \ break; \ case 0x0b: \ + case 0x13: \ dest_dat = src_dat | dest_dat; \ break; \ case 0x0c: \ @@ -207,56 +214,43 @@ mach_log(const char *fmt, ...) case 0x10: \ dest_dat = MIN(src_dat, dest_dat); \ break; \ - case 0x11: \ - dest_dat = dest_dat - src_dat; \ - break; \ - case 0x12: \ - dest_dat = src_dat - dest_dat; \ - break; \ - case 0x13: \ - dest_dat = src_dat + dest_dat; \ - break; \ case 0x14: \ dest_dat = MAX(src_dat, dest_dat); \ break; \ case 0x15: \ - dest_dat = (dest_dat - src_dat) / 2; \ + dest_dat = (src_dat | ~dest_dat) >> 1; \ break; \ case 0x16: \ - dest_dat = (src_dat - dest_dat) / 2; \ + dest_dat = (~src_dat | dest_dat) >> 1; \ break; \ case 0x17: \ - dest_dat = (dest_dat + src_dat) / 2; \ + dest_dat = (src_dat | dest_dat) >> 1; \ break; \ case 0x18: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ - break; \ case 0x19: \ - dest_dat = MAX(0, (dest_dat - src_dat)); \ + dest_dat = MAX(0, ~src_dat | dest_dat); \ break; \ case 0x1a: \ - dest_dat = MAX(0, (src_dat - dest_dat)); \ + dest_dat = MAX(0, src_dat | ~dest_dat); \ break; \ case 0x1b: \ if (dev->bpp) \ - dest_dat = MIN(0xffff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xffff, src_dat | dest_dat); \ else \ - dest_dat = MIN(0xff, (dest_dat + src_dat)); \ + dest_dat = MIN(0xff, src_dat | dest_dat); \ break; \ case 0x1c: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ - break; \ case 0x1d: \ - dest_dat = MAX(0, (dest_dat - src_dat)) / 2; \ + dest_dat = MAX(0, ~src_dat | dest_dat) >> 1; \ break; \ case 0x1e: \ - dest_dat = MAX(0, (src_dat - dest_dat)) / 2; \ + dest_dat = MAX(0, src_dat | ~dest_dat) >> 1; \ break; \ case 0x1f: \ if (dev->bpp) \ - dest_dat = (0xffff < (src_dat + dest_dat)) ? 0xffff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xffff < (src_dat | dest_dat)) ? 0xffff : ((src_dat | dest_dat) >> 1); \ else \ - dest_dat = (0xff < (src_dat + dest_dat)) ? 0xff : ((src_dat + dest_dat) / 2); \ + dest_dat = (0xff < (src_dat | dest_dat)) ? 0xff : ((src_dat | dest_dat) >> 1); \ break; \ } \ } @@ -265,10 +259,10 @@ mach_log(const char *fmt, ...) #define WRITE(addr, dat) \ if (dev->bpp) { \ vram_w[((addr)) & (dev->vram_mask >> 1)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask >> 1)) >> 11] = svga->monitor->mon_changeframecount; \ } else { \ dev->vram[((addr)) & (dev->vram_mask)] = dat; \ - dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; \ + dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; \ } static int @@ -297,6 +291,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 uint16_t rd_mask = dev->accel.rd_mask; uint16_t wrt_mask = dev->accel.wrt_mask; uint16_t dest_cmp_clr = dev->accel.color_cmp; + uint16_t frgd_color = dev->accel.frgd_color; + uint16_t bkgd_color = dev->accel.bkgd_color; int frgd_sel; int bkgd_sel; int mono_src; @@ -313,9 +309,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 int16_t clip_b = dev->accel.clip_bottom; int16_t clip_r = dev->accel.clip_right; + if (clip_l < 0) + clip_l = 0; + if (clip_t < 0) + clip_t = 0; + if (!dev->bpp) { rd_mask &= 0xff; dest_cmp_clr &= 0xff; + frgd_color &= 0xff; + bkgd_color &= 0xff; } compare_mode = (mach->accel.dest_cmp_fn >> 3) & 7; @@ -341,6 +344,8 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i.\n", cmd_type, frgd_sel, bkgd_sel, mono_src); + switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ if (!cpu_input) { @@ -438,13 +443,12 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -547,9 +551,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mono_src == 1) && !count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -662,13 +668,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -772,9 +778,11 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mono_src == 1) && !count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } else if ((mono_src != 1) && (dev->accel.sx >= mach->accel.width)) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -997,6 +1005,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dy_end == mach->accel.dy_start) { mach_log("No DEST.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } @@ -1004,6 +1013,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.sx_end == mach->accel.sx_start) { mach_log("No SRC.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -1015,6 +1025,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sy == mach->accel.height) { mach_log("No Blit on DPCONFIG=3251.\n"); dev->accel.cmd_back = 1; + dev->fifo_idx = 0; return; } } @@ -1069,7 +1080,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; if (mach->accel.dp_config & 0x02) { READ(dev->accel.src + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); @@ -1080,10 +1091,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1232,6 +1243,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sy >= mach->accel.height) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; if ((mono_src == 2) || (mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) return; if ((mono_src == 1) && (frgd_sel == 5) && (dev->accel_bpp == 24)) @@ -1311,14 +1323,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1391,6 +1403,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1445,7 +1458,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { @@ -1459,10 +1472,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1561,6 +1574,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sx >= mach->accel.width) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1604,14 +1618,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1685,6 +1699,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (!count) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1739,14 +1754,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -1843,6 +1858,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.sx >= mach->accel.width) { dev->accel.cmd_back = 1; + dev->fifo_idx = 0; break; } @@ -1873,8 +1889,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.poly_fill = 0; mach->accel.line_array[(cmd_type == 4) ? 4 : 0] = dev->accel.cx; mach->accel.line_array[(cmd_type == 4) ? 5 : 1] = dev->accel.cy; - dev->accel.cur_x = mach->accel.line_array[(cmd_type == 4) ? 4 : 0]; - dev->accel.cur_y = mach->accel.line_array[(cmd_type == 4) ? 5 : 1]; + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + mach_log("Done: %i, %i\n", dev->accel.cur_x, dev->accel.cur_y); break; case 5: /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ @@ -1920,12 +1937,16 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dest_y_end >= 0x600) mach->accel.dy_end |= ~0x5ff; - if (mach->accel.dy_end > mach->accel.dy_start) + if (mach->accel.dy_end > mach->accel.dy_start) { + dev->accel.sy = (mach->accel.dy_end - mach->accel.dy_start); mach->accel.stepy = 1; - else if (mach->accel.dy_end < mach->accel.dy_start) + } else if (mach->accel.dy_end < mach->accel.dy_start) { + dev->accel.sy = (mach->accel.dy_start - mach->accel.dy_end); mach->accel.stepy = -1; - else + } else { mach->accel.stepy = 0; + dev->accel.sy = 0; + } if (dev->bpp) dev->accel.dest = (mach->accel.ge_offset << 1) + (dev->accel.dy * (dev->pitch)); @@ -1969,9 +1990,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else dev->accel.src = (mach->accel.ge_offset << 2) + (dev->accel.cy * (dev->pitch)); - mach_log("ScanToX=%04x, MonoSRC=%d, FrgdSel=%d, BkgdSel=%d, Pitch=%d, C(%d,%d), SRCWidth=%d, WH(%d,%d), colorpattidx=%d, pattlen=%d.\n", - mach->accel.dp_config, mono_src, frgd_sel, bkgd_sel, dev->ext_pitch, dev->accel.cx, dev->accel.cy, mach->accel.src_width, - mach->accel.width, mach->accel.height, mach->accel.color_pattern_idx, mach->accel.patt_len); + mach_log("ScanToX: Parameters=%04x: DX=%d, DY=%d, CX=%d, CY=%d, dstwidth=%d, srcwidth=%d, height=%d, clipl=%d, clipr=%d, clipt=%d, clipb=%d, frmix=%02x.\n", mach->accel.dp_config, dev->accel.dx, dev->accel.dy, dev->accel.cx, dev->accel.cy, mach->accel.width, mach->accel.src_width, dev->accel.sy, clip_l, clip_r, clip_t, clip_b, dev->accel.frgd_mix & 0x1f); if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { if (mach_pixel_write(mach)) { @@ -2035,13 +2054,13 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { - dev->subsys_stat |= 0x02; + dev->subsys_stat |= INT_GE_BSY; switch (mix ? frgd_sel : bkgd_sel) { case 0: - src_dat = dev->accel.bkgd_color; + src_dat = bkgd_color; break; case 1: - src_dat = dev->accel.frgd_color; + src_dat = frgd_color; break; case 2: src_dat = cpu_dat; @@ -2104,6 +2123,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.dp_config & 0x10) { WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + mach_log("ScanToX: DXS=%d, DYS=%d, dest data=%02x, lineidx=%d.\n", dev->accel.dx, dev->accel.dy, dest_dat, mach->accel.line_idx); } } @@ -2148,7 +2168,14 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 mach->accel.line_array[0] = dev->accel.dx; mach->accel.line_array[4] = dev->accel.dx; } + if (dev->accel.sy >= 0) + dev->accel.sy--; + dev->accel.cmd_back = 1; + dev->fifo_idx = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; return; } } @@ -2278,16 +2305,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) mach->bank_r |= ((mach->regs[0xae] & 0x0c) << 2); mach->bank_w |= ((mach->regs[0xae] & 3) << 4); } - if (dev->on) - mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + mach_log("Separate B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } else { /* Single bank mode */ mach->bank_w = ((mach->regs[0xb2] & 0x1e) >> 1); if ((dev->local & 0xff) >= 0x02) mach->bank_w |= ((mach->regs[0xae] & 3) << 4); mach->bank_r = mach->bank_w; - if (dev->on) - mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); + mach_log("Single B2Bank = %02x, AEbank = %02x.\n", mach->regs[0xb2], mach->regs[0xae]); } svga->read_bank = mach->bank_r << 16; svga->write_bank = mach->bank_w << 16; @@ -2420,7 +2445,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga->fullchange = 3; svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); } else { - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; svga_recalctimings(svga); } } @@ -2490,6 +2515,7 @@ mach_in(uint16_t addr, void *priv) temp = mach->regs[mach->index]; break; } + mach_log("ATI VGA read reg=%02x, val=%02x.\n", mach->index, temp); break; case 0x2ea: @@ -2637,6 +2663,40 @@ ati_render_32bpp(svga_t *svga) } } +static void +mach_set_resolution(mach_t *mach, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->hdisp = (dev->hdisped + 1) << 3; + dev->h_total = dev->htotal + 1; + + dev->vdisp = (dev->v_disp + 1) >> 1; + if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) + dev->vdisp += 2; + + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + mach_log("Shadow set ATI=%x, shadow set 8514/A=%x, resolution h=%d, v=%d.\n", mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + if ((mach->accel.clock_sel & 0x01) || dev->bpp || ((mach->accel.ext_ge_config & 0x30) == 0x30)) /*ATI and 15bpp+ mode*/ + svga_recalctimings(svga); + else { /*8514/A mode*/ + if (mach->resolution_crt == 0x02) { + if (!(dev->accel.advfunc_cntl & 0x04)) { + dev->hdisp = 640; + dev->vdisp = 480; + svga_recalctimings(svga); + } + } + } +} + void ati8514_recalctimings(svga_t *svga) { @@ -2648,7 +2708,6 @@ ati8514_recalctimings(svga_t *svga) mach_log("8514/A ON.\n"); dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - dev->h_total = dev->htotal + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; @@ -2656,23 +2715,8 @@ ati8514_recalctimings(svga_t *svga) mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x05, mach->accel.clock_sel & 0x01); - if (mach->accel.clock_sel & 0x01) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->accel.advfunc_cntl & 0x04) { - if (dev->hdisp == 640) { - dev->h_disp = 1024; - dev->dispend = 768; - } else { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; if (dev->accel.advfunc_cntl & 0x04) svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; @@ -2695,6 +2739,7 @@ ati8514_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } @@ -2753,9 +2798,9 @@ mach_recalctimings(svga_t *svga) mach_log("ON?=%d, override=%d.\n", dev->on, svga->override); if (dev->on) { mach_log("8514/A ON, extpitch=%d, devma=%x, vgamalatch=%x.\n", dev->ext_pitch, dev->ma, svga->ma_latch); + dev->ma_latch = (mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2; dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - dev->h_total = dev->htotal + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); mach->accel.ge_offset = dev->accel.ge_offset; @@ -2763,42 +2808,12 @@ mach_recalctimings(svga_t *svga) mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x, interlace=%x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0xfe, dev->interlace); - if ((dev->local & 0xff) >= 0x02) { - if (dev->bpp || ((mach->accel.ext_ge_config & 0x30) == 0x30) || (mach->accel.clock_sel & 0x01)) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->interlace) { /*Interlaced displays are only for 800x600 and up.*/ - if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } else { - if (((mach->shadow_set & 0x03) == 0x00) && ((dev->hdisp2 == 640) || (dev->hdisp2 == 1280)) && (dev->hdisp != 800)) { - dev->h_disp = dev->hdisp2; - dev->dispend = dev->vdisp2; - } else { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } - } - } - } else { - if (mach->accel.clock_sel & 0x01) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - dev->h_disp = 640; - dev->dispend = 480; - } - } + + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + if (dev->dispend == 959) { /*FIXME: vertical resolution mess on EEPROM tests on Mach8*/ + dev->dispend >>= 1; + dev->dispend++; } svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); @@ -2809,21 +2824,29 @@ mach_recalctimings(svga_t *svga) dev->dispend >>= 1; if ((dev->local & 0xff) >= 0x02) { - mach_log("HDISP=%d, mask=%02x.\n", dev->h_disp, dev->dac_mask); + mach_log("cntl=%d, clksel=%x, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d, vgahdisp=%d.\n", + dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0x01, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, + mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace, svga->hdisp); if ((mach->accel.ext_ge_config & 0x800) || (!(mach->accel.ext_ge_config & 0x8000) && !(mach->accel.ext_ge_config & 0x800))) { if ((mach->accel.ext_ge_config & 0x30) == 0x20) { - if ((mach->accel.ext_ge_config & 0xc0) == 0x40) + if ((mach->accel.ext_ge_config & 0xc0) == 0x40) { dev->accel_bpp = 16; - else + svga->overscan_color = video_16to32[((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24) & 0xffff]; + } else { dev->accel_bpp = 15; + svga->overscan_color = video_15to32[((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24) & 0xffff]; + } } else if ((mach->accel.ext_ge_config & 0x30) == 0x30) { if (mach->accel.ext_ge_config & 0x200) dev->accel_bpp = 32; else dev->accel_bpp = 24; - } else if ((mach->accel.ext_ge_config & 0x30) == 0x10) + + svga->overscan_color = ((mach->overscan_r_col_24 << 16) | (mach->overscan_g_col_24 << 8) | mach->overscan_b_col_24); + } else if ((mach->accel.ext_ge_config & 0x30) == 0x10) { dev->accel_bpp = 8; - else { + svga->overscan_color = dev->pallook[mach->overscan_col_8]; + } else { if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2834,12 +2857,14 @@ mach_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + svga->overscan_color = dev->pallook[mach->overscan_col_8]; } - svga->render8514 = ibm8514_render_blank; mach_log("hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, bpp=%d, shadow=%x, vgahdisp=%d.\n", dev->h_disp, dev->dispend, dev->pitch, dev->ext_crt_pitch, mach->accel.ext_ge_config & 0xcec0, dev->accel_bpp, mach->shadow_set & 3, svga->hdisp); + + mach->resolution_crt = 0; switch (dev->accel_bpp) { case 8: svga->render8514 = ibm8514_render_8bpp; @@ -2864,10 +2889,9 @@ mach_recalctimings(svga_t *svga) } } } else { - svga->render8514 = ibm8514_render_blank; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", - dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, - mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); + mach_log("cntl=%d, clksel=%x, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d, vgahdisp=%d.\n", + dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0x01, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, + mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace, svga->hdisp); if (dev->vram_512k_8514) { if (dev->h_disp == 640) { dev->ext_pitch = 640; @@ -2878,6 +2902,7 @@ mach_recalctimings(svga_t *svga) } } dev->accel_bpp = 8; + mach->resolution_crt = 0; svga->render8514 = ibm8514_render_8bpp; } } else { @@ -2934,22 +2959,248 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("[%04X:%08X]: Port FIFO OUT=%04x, val=%04x, len=%d.\n", CS, cpu_state.pc, port, val, len); switch (port) { + case 0x2e8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) + dev->htotal = val; + + mach_set_resolution(mach, svga); + } + break; + + case 0xae8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + WRITE8(port, dev->hsync_start, val); + } + svga_recalctimings(svga); + } + break; + + case 0xee8: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + WRITE8(port, dev->hsync_width, val); + } + svga_recalctimings(svga); + } + break; + + case 0x1ee8: + case 0x1ee9: + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) /*For 8514/A mode, take the shadow sets into account.*/ + svga_recalctimings(svga); + break; + + case 0x6e8: + if (len == 2) { + mach_log("HDISP and HTOTAL=%04x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + + if (!(mach->shadow_cntl & 0x04)) + dev->htotal = (val >> 8) & 0xff; + + mach_set_resolution(mach, svga); + } + } else { + mach_log("HDISP and HTOTAL=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + mach_set_resolution(mach, svga); + } else if (!(mach->accel.clock_sel & 0x01) && ((mach->shadow_set & 0x03) == 0x00) && dev->on) { /*Still write the parameter even after going to 8514/A mode if needed*/ + if (!(mach->shadow_cntl & 0x08)) { + WRITE8(port, dev->hdisped, val); + } + if (mach->resolution_crt == 0x00) + mach->resolution_crt = 0x02; + + mach_set_resolution(mach, svga); + } + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x, shadowcntl=%02x, shadowset=%02x.\n", + CS, cpu_state.pc, port, val, mach->shadow_cntl & 0x08, mach->shadow_set & 0x03); + break; + + case 0x6e9: + if (len == 1) { + mach_log("HDISP and HTOTAL+1=%02x, len=%d, set=%x, ATI mode bit=%x.\n", val, len, mach->shadow_set & 0x03, mach->accel.clock_sel & 0x01); + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x04)) { + dev->htotal = val; + } + mach_set_resolution(mach, svga); + } + } + break; + + case 0x12e8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x10)) { + dev->v_total_reg = val; + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { /*For 8514/A mode, take the shadow sets into account.*/ + if (!(mach->shadow_cntl & 0x10)) { + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + break; + + case 0x12e9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + } + break; + + case 0x16e8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + dev->v_disp = val; + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + break; + case 0x16e9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x20)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_disp, val); + dev->v_disp &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); + mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + } + break; + + case 0x1ae8: + if (len == 2) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + dev->v_sync_start = val; + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); + } else { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + } + break; + case 0x1ae9: + if (len == 1) { + if ((mach->accel.clock_sel & 0x01) || (!(mach->accel.clock_sel & 0x01) && (mach->shadow_set & 0x03))) { + if (!(mach->shadow_cntl & 0x10)) { /*For 8514/A mode, take the shadow sets into account.*/ + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + } + mach_set_resolution(mach, svga); + } + mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); + } + break; + + case 0x22e8: + if ((mach->shadow_cntl & 0x03) == 0x00) { + dev->disp_cntl = val; + dev->interlace = !!(dev->disp_cntl & 0x10); + } + mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%d.\n", + port, val & 0x70, dev->disp_cntl & 0x70, dev->interlace); + svga_recalctimings(svga); + break; + + + case 0x42e8: + case 0x42e9: + mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + if (len == 2) + dev->subsys_cntl = val; + else { + WRITE8(port, dev->subsys_cntl, val); + } + dev->subsys_stat &= ~val; + if ((dev->subsys_cntl & 0xc000) == 0x8000) { + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + } + break; + + case 0x46e8: + case 0x46e9: + mach_log("0x%04x write: VGA subsystem enable add-on=%02x.\n", port, val); + break; + + case 0x4ae8: + dev->accel.advfunc_cntl = val; + dev->on = dev->accel.advfunc_cntl & 0x01; + dev->vendor_mode = 0; + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", + CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + + if ((dev->local & 0xff) < 0x02) { + dev->ext_crt_pitch = 128; + mach_set_resolution(mach, svga); + } else { + mach_set_resolution(mach, svga); + mach32_updatemapping(mach, svga); + } + mach_log("Vendor IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); + break; + case 0x82e8: case 0x86e8: case 0xc2e8: case 0xc6e8: - dev->ext_fifo_idx++; - ibm8514_accel_out_fifo(svga, port, val, len); - break; case 0xf6ee: - dev->ext_fifo_idx++; - if (len == 2) - dev->accel.cur_y = val & 0x7ff; + ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x8ae8: case 0xcae8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCY=%d.\n", val & 0x07ff); @@ -2959,7 +3210,6 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x8ee8: case 0xcee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { mach_log("SRCX=%d.\n", val & 0x07ff); @@ -2969,13 +3219,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x92e8: case 0xd2e8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x96e8: case 0xd6e8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) mach->accel.test = val & 0x1fff; @@ -2983,34 +3231,42 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x9ae8: case 0xdae8: - dev->ext_fifo_idx++; mach->accel.cmd_type = -1; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x9ee8: case 0xdee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xa2e8: case 0xe2e8: - dev->ext_fifo_idx++; - dev->fifo_idx++; if (port == 0xe2e8) { if (len == 2) { if (dev->accel.cmd_back) { - dev->accel.bkgd_color = val; - mach_log("CMDBack BKGDCOLOR, sy=%d, height=%d, val=%04x.\n", dev->accel.sy, mach->accel.height, val); + if (mach->accel.cmd_type == 5) { + if (dev->accel.sy >= 0) { + if (mach_pixel_read(mach)) + break; + + mach_accel_out_pixtrans(svga, mach, dev, val); + } else + dev->accel.bkgd_color = val; + } else + dev->accel.bkgd_color = val; + + mach_log("%04X: CMDBack BKGDCOLOR, sy=%d, height=%d, val=%04x.\n", port, dev->accel.sy, mach->accel.height, val); } else { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + ibm8514_accel_out_pixtrans(svga, port, val, len); } } @@ -3018,31 +3274,43 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[1] = val; } } } else { if (len == 2) dev->accel.bkgd_color = val; + + mach_log("%04X: Background Color=%04x.\n", port, val); } break; case 0xa6e8: case 0xe6e8: - dev->ext_fifo_idx++; - dev->fifo_idx++; if (port == 0xe6e8) { if (len == 2) { - if (dev->accel.cmd_back) - dev->accel.frgd_color = val; - else { + if (dev->accel.cmd_back) { + if (mach->accel.cmd_type == 5) { + if (dev->accel.sy >= 0) { + if (mach_pixel_read(mach)) + break; + + mach_accel_out_pixtrans(svga, mach, dev, val); + } else + dev->accel.frgd_color = val; + } else + dev->accel.frgd_color = val; + } else { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach_accel_out_pixtrans(svga, mach, dev, val); } else { if (ibm8514_cpu_dest(svga)) break; + ibm8514_accel_out_pixtrans(svga, port, val, len); } } @@ -3050,6 +3318,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[1] = val; } } @@ -3061,13 +3330,12 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xe2e9: case 0xe6e9: - dev->ext_fifo_idx++; - dev->fifo_idx++; mach_log("Write PORT=%04x, 8514/A=%x, val=%04x, len=%d.\n", port, dev->accel.cmd_back, val, len); if (len == 1) { if (mach->accel.cmd_type >= 0) { if (mach_pixel_read(mach)) break; + mach->accel.pix_trans[0] = val; frgd_sel = (mach->accel.dp_config >> 13) & 7; bkgd_sel = (mach->accel.dp_config >> 7) & 3; @@ -3114,13 +3382,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xf2e8: case 0xf6e8: case 0xfae8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xbee8: case 0xfee8: - dev->ext_fifo_idx++; ibm8514_accel_out_fifo(svga, port, val, len); if (len == 2) { if ((dev->accel.multifunc_cntl >> 12) == 5) { @@ -3131,485 +3397,95 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; /*ATI Mach8/32 specific registers*/ - case 0x82ee: - dev->ext_fifo_idx++; - mach->accel.patt_data_idx_reg = val & 0x1f; - mach->accel.patt_data_idx = mach->accel.patt_data_idx_reg; - - if (mach->accel.patt_data_idx_reg < 0x10) - mach->accel.color_pattern_idx = mach->accel.patt_idx; - else - mach->accel.color_pattern_idx = 0; - - mach_log("Write Port 82ee: Pattern Data Index=%d.\n", val & 0x1f); - break; - - case 0x8eee: - dev->ext_fifo_idx++; - if (len == 2) { - if (mach->accel.patt_data_idx_reg < 0x10) { - mach->accel.color_pattern[mach->accel.patt_data_idx] = val & 0xff; - mach->accel.color_pattern[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; - mach_log("Write Port 8eee: Color Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx, val); - } else { - mach->accel.mono_pattern_normal[mach->accel.patt_data_idx - 0x10] = val & 0xff; - mach->accel.mono_pattern_normal[(mach->accel.patt_data_idx + 1) - 0x10] = (val >> 8) & 0xff; - mach_log("Write Port 8eee: Mono Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx - 0x10, val); - } - mach->accel.patt_data_idx += 2; - } - break; - - case 0x96ee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.bres_count = val & 0x7ff; - mach_log("BresenhamDraw=%04x.\n", mach->accel.dp_config); - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.cmd_type = 1; - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0x9aee: - dev->ext_fifo_idx++; - mach->accel.line_idx = val & 0x07; - break; - - case 0xa2ee: - dev->ext_fifo_idx++; - mach_log("Line OPT=%04x.\n", val); - if (len == 2) { - mach->accel.linedraw_opt = val; - mach->accel.bbottom = dev->accel.clip_bottom; - mach->accel.btop = dev->accel.clip_top; - mach->accel.bleft = dev->accel.clip_left; - mach->accel.bright = dev->accel.clip_right; - if (mach->accel.linedraw_opt & 0x100) { - mach->accel.bbottom = 2047; - mach->accel.btop = 0; - mach->accel.bleft = 0; - mach->accel.bright = 2047; - } - } - break; - - case 0xa6ee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_x_start = val & 0x7ff; - break; - - case 0xaaee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_x_end = val & 0x7ff; - break; - - case 0xaeee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.dest_y_end = val & 0x7ff; - if ((val + 1) == 0x10000) { - mach_log("Dest_Y_end overflow val=%04x, DPCONFIG=%04x\n", val, mach->accel.dp_config); - mach->accel.dest_y_end = 0; - } - dev->data_available = 0; - dev->data_available2 = 0; - mach_log("BitBLT=%04x.\n", mach->accel.dp_config); - mach_log(".\n"); - mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ - - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0xb2ee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.src_x_start = val & 0x7ff; - break; - - case 0xb6ee: - dev->ext_fifo_idx++; - dev->accel.bkgd_mix = val & 0xff; - break; - - case 0xbaee: - dev->ext_fifo_idx++; - dev->accel.frgd_mix = val & 0xff; - break; - - case 0xbeee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.src_x_end = val & 0x7ff; - break; - - case 0xc2ee: - dev->ext_fifo_idx++; - mach->accel.src_y_dir = val & 1; - break; - - case 0xc6ee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.cmd_type = 0; - mach_log("TODO: Short Stroke.\n"); - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - } - break; - - case 0xcaee: - dev->ext_fifo_idx++; - if (len == 2) { - mach->accel.scan_to_x = (val & 0x7ff); - if ((val + 1) == 0x10000) { - mach_log("Scan_to_X overflow val = %04x\n", val); - mach->accel.scan_to_x = 0; - } - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ - mach_log("ScanToX=%04x.\n", mach->accel.dp_config); - mach_log(".\n"); - - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - } - break; - - case 0xceee: - dev->ext_fifo_idx++; - mach_log("CEEE write val = %04x.\n", val); - if (len == 2) { - dev->data_available = 0; - dev->data_available2 = 0; - mach->accel.dp_config = val; - } - break; - - case 0xd2ee: - dev->ext_fifo_idx++; - mach->accel.patt_len = val & 0x1f; - mach_log("Write Port d2ee: Pattern Length=%d, val=%04x.\n", val & 0x1f, val); - mach->accel.mono_pattern_enable = !!(val & 0x80); - if (len == 2) { - mach->accel.block_write_mono_pattern_enable = !!(val & 0x8000); - mach->accel.patt_len_reg = val; - } - break; - - case 0xd6ee: - dev->ext_fifo_idx++; - mach->accel.patt_idx = val & 0x1f; - mach_log("Write Port d6ee: Pattern Index=%d.\n", val & 0x1f); - break; - - case 0xdaee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[2] = val & 0x7ff; - dev->accel.clip_left = dev->accel.multifunc[2]; - if (val & 0x800) - dev->accel.clip_left |= ~0x7ff; - } - mach_log("DAEE (extclipl) write val=%d, left=%d.\n", val, dev->accel.clip_left); - break; - - case 0xdeee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[1] = val & 0x7ff; - dev->accel.clip_top = dev->accel.multifunc[1]; - if (val & 0x800) { - dev->accel.clip_top |= ~0x7ff; - } - } - mach_log("DEEE (extclipt) write val = %d\n", val); - break; - - case 0xe2ee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[4] = val & 0x7ff; - dev->accel.clip_right = dev->accel.multifunc[4]; - if (val & 0x800) - dev->accel.clip_right |= ~0x7ff; - } - mach_log("E2EE (extclipr) write val = %d\n", val); - break; - - case 0xe6ee: - dev->ext_fifo_idx++; - if (len == 2) { - dev->accel.multifunc[3] = val & 0x7ff; - dev->accel.clip_bottom = dev->accel.multifunc[3]; - if (val & 0x800) - dev->accel.clip_bottom |= ~0x7ff; - } - mach_log("E6EE (extclipb) write val = %d\n", val); - break; - - case 0xeeee: - dev->ext_fifo_idx++; - if (len == 2) - mach->accel.dest_cmp_fn = val; - break; - - case 0xf2ee: - dev->ext_fifo_idx++; - mach_log("F2EE.\n"); - if (len == 2) - mach->accel.dst_clr_cmp_mask = val; - break; - - case 0xfeee: - dev->ext_fifo_idx++; - mach_log("LineDraw=%04x.\n", mach->accel.dp_config); - if (len == 2) { - mach->accel.line_array[mach->accel.line_idx] = val; - dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; - dev->accel.cur_y = mach->accel.line_array[(mach->accel.line_idx == 5) ? 5 : 1]; - mach->accel.cx_end_line = mach->accel.line_array[2]; - mach->accel.cy_end_line = mach->accel.line_array[3]; - if ((mach->accel.line_idx == 3) || (mach->accel.line_idx == 5)) { - mach->accel.cmd_type = (mach->accel.line_idx == 5) ? 4 : 3; - frgd_sel = (mach->accel.dp_config >> 13) & 7; - bkgd_sel = (mach->accel.dp_config >> 7) & 3; - mono_src = (mach->accel.dp_config >> 5) & 3; - - dev->accel.cmd_back = 1; - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) - dev->accel.cmd_back = 0; - - mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); - mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; - break; - } - mach->accel.line_idx++; - } - break; - - default: - break; - } -} - -static void -mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) -{ - if (port == 0x42e8 || port == 0x42e9) - mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); - - switch (port) { - case 0x2e8: - case 0x6e9: - case 0xae8: - case 0xee8: - case 0x1ee8: - case 0x1ee9: - case 0x42e8: - ibm8514_accel_out(port, val, svga, 2); - break; - case 0x42e9: - ibm8514_accel_out(port, val, svga, 2); - if ((val & 0xc0) == 0x80) { - dev->ext_fifo_idx = 0; - mach->force_busy = 0; - } - break; - - case 0x6e8: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x08)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01)) { - dev->hdisped = val; - dev->hdisp = (val + 1) << 3; - } else if (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01)) - dev->hdisp2 = (val + 1) << 3; - } - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x, shadowcntl=%02x, shadowset=%02x.\n", - CS, cpu_state.pc, port, val, mach->shadow_cntl & 0x08, mach->shadow_set & 0x03); - svga_recalctimings(svga); - break; - - case 0x12e8: - case 0x12e9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x10)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; - dev->v_total = dev->v_total_reg + 1; - if (dev->interlace) - dev->v_total >>= 1; - } - } - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); - svga_recalctimings(svga); - break; - - case 0x16e8: - case 0x16e9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x20)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_disp, val); - dev->v_disp &= 0x1fff; - dev->vdisp = (dev->v_disp + 1) >> 1; - if ((dev->vdisp == 478) || (dev->vdisp == 598) || (dev->vdisp == 766) || (dev->vdisp == 1022)) - dev->vdisp += 2; - } else if (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_disp2, val); - dev->v_disp2 &= 0x1fff; - dev->vdisp2 = (dev->v_disp2 + 1) >> 1; - if ((dev->vdisp2 == 478) || (dev->vdisp2 == 598) || (dev->vdisp2 == 766) || (dev->vdisp2 == 1022)) - dev->vdisp2 += 2; - } - } - mach_log("ATI 8514/A: V_DISP write 16E8=%d, vdisp2=%d.\n", dev->v_disp, dev->v_disp2); - mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x1ae8: - case 0x1ae9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!(mach->shadow_cntl & 0x10)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - dev->v_syncstart = dev->v_sync_start + 1; - if (dev->interlace) - dev->v_syncstart >>= 1; - } - } - mach_log("ATI 8514/A: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); - mach_log("ATI 8514/A: (0x%04x): vsyncstart=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - - case 0x22e8: - if (!(mach->shadow_cntl & 0x03)) { - if ((mach->shadow_set & 0x03) || (mach->accel.clock_sel & 0x01) || - (((mach->shadow_set & 0x03) == 0x00) && !(mach->accel.clock_sel & 0x01))) { - dev->disp_cntl = val; - dev->interlace = !!(dev->disp_cntl & 0x10); - } - } - mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, written=%02x, interlace=%d.\n", - port, val & 0x70, dev->disp_cntl & 0x70, dev->interlace); - svga_recalctimings(svga); - break; - - case 0x46e8: - case 0x46e9: - mach_log("0x%04x write: VGA subsystem enable add-on=%02x.\n", port, val); - break; - - case 0x4ae8: - dev->accel.advfunc_cntl = val; - dev->on = dev->accel.advfunc_cntl & 0x01; - dev->vendor_mode = 0; - mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", - CS, cpu_state.pc, port, val & 0x01, dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); - - if ((dev->local & 0xff) < 0x02) { - dev->ext_crt_pitch = 128; - svga_recalctimings(svga); - } else { - svga_recalctimings(svga); - mach32_updatemapping(mach, svga); - } - mach_log("Vendor IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); - break; - - /*ATI Mach8/32 specific registers*/ case 0x2ee: - mach_log("2EE write val = %02x.\n", val); - break; case 0x2ef: - mach_log("2EF write val = %02x.\n", val); + if (len == 2) { + mach->overscan_col_8 = val & 0xff; + mach->overscan_b_col_24 = (val >> 8) & 0xff; + } else { + if (port & 1) + mach->overscan_b_col_24 = val; + else + mach->overscan_col_8 = val; + } + svga_recalctimings(svga); break; - case 0x6ee: - mach_log("6EE write val = %02x.\n", val); - break; case 0x6ef: - mach_log("6EF write val = %02x.\n", val); + if (len == 2) { + mach->overscan_g_col_24 = val & 0xff; + mach->overscan_r_col_24 = (val >> 8) & 0xff; + } else { + if (port & 1) + mach->overscan_r_col_24 = val; + else + mach->overscan_g_col_24 = val; + } + svga_recalctimings(svga); break; case 0xaee: case 0xaef: - WRITE8(port, mach->cursor_offset_lo_reg, val); + if (len == 2) + mach->cursor_offset_lo_reg = val; + else { + WRITE8(port, mach->cursor_offset_lo_reg, val); + } mach->cursor_offset_lo = mach->cursor_offset_lo_reg; dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); break; case 0xeee: case 0xeef: - WRITE8(port, mach->cursor_offset_hi_reg, val); + if (len == 2) + mach->cursor_offset_hi_reg = val; + else { + WRITE8(port, mach->cursor_offset_hi_reg, val); + } + dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); mach->cursor_offset_hi = mach->cursor_offset_hi_reg & 0x0f; dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); - dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); mach_log("HWCursorEnabled=%x.\n", dev->hwcursor.ena); break; case 0x12ee: case 0x12ef: - WRITE8(port, mach->cursor_x, val); + if (len == 2) + mach->cursor_x = val; + else { + WRITE8(port, mach->cursor_x, val); + } dev->hwcursor.x = mach->cursor_x & 0x7ff; break; case 0x16ee: case 0x16ef: - WRITE8(port, mach->cursor_y, val); + if (len == 2) + mach->cursor_y = val; + else { + WRITE8(port, mach->cursor_y, val); + } dev->hwcursor.y = mach->cursor_y & 0xfff; break; case 0x1aee: case 0x1aef: - WRITE8(port, mach->cursor_col_b, val); + if (len == 2) + mach->cursor_col_b = val; + else { + WRITE8(port, mach->cursor_col_b, val); + } mach->cursor_col_0 = mach->cursor_col_b & 0xff; mach->cursor_col_1 = (mach->cursor_col_b >> 8) & 0xff; break; case 0x1eee: case 0x1eef: - WRITE8(port, mach->cursor_vh_offset, val); + if (len == 2) + mach->cursor_vh_offset = val; + else { + WRITE8(port, mach->cursor_vh_offset, val); + } dev->hwcursor.xoff = mach->cursor_vh_offset & 0x3f; dev->hwcursor.yoff = (mach->cursor_vh_offset >> 8) & 0x3f; break; @@ -3624,7 +3500,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x26ee: case 0x26ef: - WRITE8(port, mach->accel.crt_pitch, val); + if (len == 2) + mach->accel.crt_pitch = val; + else { + WRITE8(port, mach->accel.crt_pitch, val); + } dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; if (dev->accel_bpp > 8) { if (dev->accel_bpp == 24) @@ -3642,54 +3522,98 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 if ((dev->local & 0xff) >= 0x01) mach32_updatemapping(mach, svga); - mach_log("ATI 8514/A: (0x%04x) val=0x%02x, extended 8514/A mode=%02x.\n", port, val, mach->regs[0xb0] & 0x20); + mach_log("ATI 8514/A: (0x%04x) CRT Pitch, val=0x%02x, crtpitch=%x, len=%d, extended 8514/A mode=%02x.\n", port, val, dev->ext_crt_pitch, len, mach->regs[0xb0] & 0x20); + break; + + case 0x2aee: + case 0x2aef: + if (len == 2) { + mach->accel.crt_offset_lo = val; + } else { + WRITE8(port, mach->accel.crt_offset_lo, val); + } + svga_recalctimings(svga); + break; + + case 0x2eee: + case 0x2eef: + mach->accel.crt_offset_hi = val & 0x0f; + svga_recalctimings(svga); break; case 0x32ee: case 0x32ef: - WRITE8(port, mach->local_cntl, val); + if (len == 2) + mach->local_cntl = val; + else { + WRITE8(port, mach->local_cntl, val); + } if ((dev->local & 0xff) >= 0x01) mach32_updatemapping(mach, svga); break; case 0x36ee: case 0x36ef: - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); - if ((dev->local & 0xff) >= 0x02) { - WRITE8(port, mach->misc, val); - mach->misc &= 0xfff0; + if (len == 2) { + if ((dev->local & 0xff) >= 0x02) + mach->misc = val; + } else { + if ((dev->local & 0xff) >= 0x02) + WRITE8(port, mach->misc, val); } + mach->misc &= 0xfff0; break; case 0x3aee: case 0x3aef: - WRITE8(port, mach->cursor_col_0_rg, val); + if (len == 2) + mach->cursor_col_0_rg = val; + else { + WRITE8(port, mach->cursor_col_0_rg, val); + } mach->ext_cur_col_0_g = mach->cursor_col_0_rg & 0xff; mach->ext_cur_col_0_r = (mach->cursor_col_0_rg >> 8) & 0xff; break; case 0x3eee: case 0x3eef: - WRITE8(port, mach->cursor_col_1_rg, val); + if (len == 2) + mach->cursor_col_1_rg = val; + else { + WRITE8(port, mach->cursor_col_1_rg, val); + } mach->ext_cur_col_1_g = mach->cursor_col_1_rg & 0xff; mach->ext_cur_col_1_r = (mach->cursor_col_1_rg >> 8) & 0xff; break; case 0x42ee: case 0x42ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.test2, val); + if (len == 2) + mach->accel.test2 = val; + else { + WRITE8(port, mach->accel.test2, val); + } + mach_log("ATI 8514/A: (0x%04x) MEM_BNDRY val=%04x, memory part=%06x, gdcreg6=%02x.\n", port, val, (mach->accel.test2 & 0x0f) << 18, svga->gdcreg[6] & 0x0c); + mach32_updatemapping(mach, svga); break; case 0x46ee: case 0x46ef: - WRITE8(port, mach->shadow_cntl, val); + if (len == 2) + mach->shadow_cntl = val; + else { + WRITE8(port, mach->shadow_cntl, val); + } mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); break; case 0x4aee: case 0x4aef: - WRITE8(port, mach->accel.clock_sel, val); + if (len == 2) + mach->accel.clock_sel = val; + else { + WRITE8(port, mach->accel.clock_sel, val); + } dev->on = mach->accel.clock_sel & 0x01; dev->vendor_mode = 1; mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", @@ -3703,31 +3627,50 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x52ee: case 0x52ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.scratch0, val); + mach_log("ATI 8514/A: (0x%04x) ScratchPad0 val=%04x.\n", port, val); + if (len == 2) + mach->accel.scratch0 = val; + else { + WRITE8(port, mach->accel.scratch0, val); + } break; case 0x56ee: case 0x56ef: - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); - WRITE8(port, mach->accel.scratch1, val); + mach_log("ATI 8514/A: (0x%04x) ScratchPad1 val=%04x.\n", port, val); + if (len == 2) + mach->accel.scratch1 = val; + else { + WRITE8(port, mach->accel.scratch1, val); + } break; case 0x5aee: case 0x5aef: - WRITE8(port, mach->shadow_set, val); + if (len == 2) + mach->shadow_set = val; + else { + WRITE8(port, mach->shadow_set, val); + } mach_log("ATI 8514/A: (0x%04x) val=0x%02x.\n", port, val); if ((mach->shadow_set & 0x03) == 0x00) mach_log("Primary CRT register set.\n"); - else if ((mach->shadow_set & 0x03) == 0x01) + else if ((mach->shadow_set & 0x03) == 0x01) { mach_log("CRT Shadow Set 1: 640x480.\n"); - else if ((mach->shadow_set & 0x03) == 0x02) + mach->resolution_crt = 0x01; + } else if ((mach->shadow_set & 0x03) == 0x02) { mach_log("CRT Shadow Set 2: 1024x768.\n"); + mach->resolution_crt = 0x02; + } break; case 0x5eee: case 0x5eef: - WRITE8(port, mach->memory_aperture, val); + if (len == 2) + mach->memory_aperture = val; + else { + WRITE8(port, mach->memory_aperture, val); + } mach_log("Memory Aperture = %04x.\n", mach->memory_aperture); if (!mach->pci_bus) mach->linear_base = (mach->memory_aperture & 0xff00) << 12; @@ -3736,36 +3679,44 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach32_updatemapping(mach, svga); break; - case 0x62ee: - mach_log("62EE write val = %04x, len = %d.\n", val, len); - break; - - case 0x66ee: - mach_log("66EE write val = %04x, len = %d.\n", val, len); - break; - case 0x6aee: case 0x6aef: - WRITE8(port, mach->accel.max_waitstates, val); + if (len == 2) + mach->accel.max_waitstates = val; + else { + WRITE8(port, mach->accel.max_waitstates, val); + } break; case 0x6eee: case 0x6eef: - WRITE8(port, mach->accel.ge_offset_lo, val); + if (len == 2) + mach->accel.ge_offset_lo = val; + else { + WRITE8(port, mach->accel.ge_offset_lo, val); + } svga_recalctimings(svga); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, geoffset=%04x.\n", port, val, dev->accel.ge_offset); break; case 0x72ee: case 0x72ef: - WRITE8(port, mach->accel.ge_offset_hi, val); + if (len == 2) + mach->accel.ge_offset_hi = val; + else { + WRITE8(port, mach->accel.ge_offset_hi, val); + } svga_recalctimings(svga); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, geoffset=%04x.\n", port, val, dev->accel.ge_offset); break; case 0x76ee: case 0x76ef: - WRITE8(port, mach->accel.ge_pitch, val); + if (len == 2) + mach->accel.ge_pitch = val; + else { + WRITE8(port, mach->accel.ge_pitch, val); + } dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); mach_log("ATI 8514/A: (0x%04x) val=0x%02x, extpitch=%d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); @@ -3773,7 +3724,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x7aee: case 0x7aef: - WRITE8(port, mach->accel.ext_ge_config, val); + if (len == 2) + mach->accel.ext_ge_config = val; + else { + WRITE8(port, mach->accel.ext_ge_config, val); + } if ((dev->local & 0xff) >= 0x02) { if (mach->accel.crt_pitch & 0xff) dev->ext_crt_pitch = mach->accel.crt_pitch & 0xff; @@ -3802,24 +3757,295 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); svga_recalctimings(svga); } else - ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x4000), !!(mach->accel.ext_ge_config & 0x2000), !!(mach->accel.ext_ge_config & 0x1000)); + ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x04), !!(mach->accel.ext_ge_config & 0x02), !!(mach->accel.ext_ge_config & 0x01)); + break; + + case 0x7eee: + case 0x7eef: + if (len == 2) + mach->accel.eeprom_control = val; + else { + WRITE8(port, mach->accel.eeprom_control, val); + } + mach_log("%04X write val=%04x, actual=%04x, len=%d.\n", port, mach->accel.eeprom_control, val, len); + break; + + case 0x82ee: + mach->accel.patt_data_idx_reg = val & 0x1f; + mach->accel.patt_data_idx = mach->accel.patt_data_idx_reg; + + if (mach->accel.patt_data_idx_reg < 0x10) + mach->accel.color_pattern_idx = mach->accel.patt_idx; + else + mach->accel.color_pattern_idx = 0; + + mach_log("Write Port 82ee: Pattern Data Index=%d.\n", val & 0x1f); + break; + + case 0x8eee: + if (len == 2) { + if (mach->accel.patt_data_idx_reg < 0x10) { + mach->accel.color_pattern[mach->accel.patt_data_idx] = val & 0xff; + mach->accel.color_pattern[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; + mach_log("Write Port 8eee: Color Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx, val); + } else { + mach->accel.mono_pattern_normal[mach->accel.patt_data_idx - 0x10] = val & 0xff; + mach->accel.mono_pattern_normal[(mach->accel.patt_data_idx + 1) - 0x10] = (val >> 8) & 0xff; + mach_log("Write Port 8eee: Mono Pattern Word Data[%d]=%04x.\n", mach->accel.patt_data_idx - 0x10, val); + } + mach->accel.patt_data_idx += 2; + } + break; + + case 0x92ee: + mach_log("Write port 92ee, malatch=%08x.\n", svga->ma_latch); + break; + + case 0x96ee: + if (len == 2) { + mach->accel.bres_count = val & 0x7ff; + mach_log("BresenhamDraw=%04x.\n", mach->accel.dp_config); + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 1; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0x9aee: + mach->accel.line_idx = val & 0x07; + break; + + case 0xa2ee: + mach_log("Line OPT=%04x.\n", val); + if (len == 2) { + mach->accel.linedraw_opt = val; + mach->accel.bbottom = dev->accel.clip_bottom; + mach->accel.btop = dev->accel.clip_top; + mach->accel.bleft = dev->accel.clip_left; + mach->accel.bright = dev->accel.clip_right; + if (mach->accel.linedraw_opt & 0x100) { + mach->accel.bbottom = 2047; + mach->accel.btop = 0; + mach->accel.bleft = 0; + mach->accel.bright = 2047; + } + } + break; + + case 0xa6ee: + if (len == 2) + mach->accel.dest_x_start = val & 0x7ff; + break; + + case 0xaaee: + if (len == 2) + mach->accel.dest_x_end = val & 0x7ff; + break; + + case 0xaeee: + if (len == 2) { + mach->accel.dest_y_end = val & 0x7ff; + if ((val + 1) == 0x10000) { + mach_log("Dest_Y_end overflow val=%04x, DPCONFIG=%04x\n", val, mach->accel.dp_config); + mach->accel.dest_y_end = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach_log("BitBLT=%04x.\n", mach->accel.dp_config); + mach_log(".\n"); + mach->accel.cmd_type = 2; /*Non-conforming BitBLT from dest_y_end register (0xaeee)*/ + + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0xb2ee: + if (len == 2) + mach->accel.src_x_start = val & 0x7ff; + break; + + case 0xb6ee: + dev->accel.bkgd_mix = val & 0xff; + break; + + case 0xbaee: + dev->accel.frgd_mix = val & 0xff; + break; + + case 0xbeee: + if (len == 2) + mach->accel.src_x_end = val & 0x7ff; + break; + + case 0xc2ee: + mach->accel.src_y_dir = val & 1; + break; + + case 0xc6ee: + if (len == 2) { + mach->accel.cmd_type = 0; + mach_log("TODO: Short Stroke.\n"); + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + } + break; + + case 0xcaee: + if (len == 2) { + mach->accel.scan_to_x = (val & 0x7ff); + if ((val + 1) == 0x10000) { + mach_log("Scan_to_X overflow val = %04x\n", val); + mach->accel.scan_to_x = 0; + } + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.cmd_type = 5; /*Horizontal Raster Draw from scan_to_x register (0xcaee)*/ + mach_log(".\n"); + + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_log("ScanToX=%04x, mono_src=%d, bkgd_sel=%d, frgd_sel=%d, pixread=%x.\n", mach->accel.dp_config, mono_src, bkgd_sel, frgd_sel, mach_pixel_read(mach)); + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + } + break; + + case 0xceee: + mach_log("Data Path Configuration (%04x) write val=%04x.\n", port, val); + if (len == 2) { + dev->data_available = 0; + dev->data_available2 = 0; + mach->accel.dp_config = val; + } + break; + + case 0xd2ee: + mach->accel.patt_len = val & 0x1f; + mach_log("Write Port d2ee: Pattern Length=%d, val=%04x.\n", val & 0x1f, val); + mach->accel.mono_pattern_enable = !!(val & 0x80); + if (len == 2) { + mach->accel.block_write_mono_pattern_enable = !!(val & 0x8000); + mach->accel.patt_len_reg = val; + } + break; + + case 0xd6ee: + mach->accel.patt_idx = val & 0x1f; + mach_log("Write Port d6ee: Pattern Index=%d.\n", val & 0x1f); + break; + + case 0xdaee: + if (len == 2) { + dev->accel.multifunc[2] = val & 0x7ff; + dev->accel.clip_left = dev->accel.multifunc[2]; + if (val & 0x800) + dev->accel.clip_left |= ~0x7ff; + } + mach_log("DAEE (extclipl) write val=%d, left=%d.\n", val, dev->accel.clip_left); + break; + + case 0xdeee: + if (len == 2) { + dev->accel.multifunc[1] = val & 0x7ff; + dev->accel.clip_top = dev->accel.multifunc[1]; + if (val & 0x800) { + dev->accel.clip_top |= ~0x7ff; + } + } + mach_log("DEEE (extclipt) write val = %d\n", val); + break; + + case 0xe2ee: + if (len == 2) { + dev->accel.multifunc[4] = val & 0x7ff; + dev->accel.clip_right = dev->accel.multifunc[4]; + if (val & 0x800) + dev->accel.clip_right |= ~0x7ff; + } + mach_log("E2EE (extclipr) write val = %d\n", val); + break; + + case 0xe6ee: + if (len == 2) { + dev->accel.multifunc[3] = val & 0x7ff; + dev->accel.clip_bottom = dev->accel.multifunc[3]; + if (val & 0x800) + dev->accel.clip_bottom |= ~0x7ff; + } + mach_log("E6EE (extclipb) write val = %d\n", val); + break; + + case 0xeeee: + if (len == 2) + mach->accel.dest_cmp_fn = val; + break; + + case 0xf2ee: + mach_log("F2EE.\n"); + if (len == 2) + mach->accel.dst_clr_cmp_mask = val; + break; + + case 0xfeee: + if (len == 2) { + mach->accel.line_array[mach->accel.line_idx] = val; + mach_log("mach->accel.line_array[%02X] = %04X\n", mach->accel.line_idx, val); + dev->accel.cur_x = mach->accel.line_array[(mach->accel.line_idx == 4) ? 4 : 0]; + dev->accel.cur_y = mach->accel.line_array[(mach->accel.line_idx == 5) ? 5 : 1]; + mach->accel.cx_end_line = mach->accel.line_array[2]; + mach->accel.cy_end_line = mach->accel.line_array[3]; + if ((mach->accel.line_idx == 3) || (mach->accel.line_idx == 5)) { + mach->accel.cmd_type = (mach->accel.line_idx == 5) ? 4 : 3; + frgd_sel = (mach->accel.dp_config >> 13) & 7; + bkgd_sel = (mach->accel.dp_config >> 7) & 3; + mono_src = (mach->accel.dp_config >> 5) & 3; + + dev->accel.cmd_back = 1; + if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) + dev->accel.cmd_back = 0; + + mach_log("LineDraw type=%x, dpconfig=%04x.\n", mach->accel.cmd_type, mach->accel.dp_config); + mach_accel_start(mach->accel.cmd_type, 0, -1, -1, 0, svga, mach, dev); + mach->accel.line_idx = (mach->accel.line_idx == 5) ? 4 : 2; + break; + } + mach->accel.line_idx++; + } break; default: + mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->ma_latch); break; } } -static void -mach_accel_out(uint16_t port, uint8_t val, mach_t *mach) -{ - svga_t *svga = &mach->svga; - - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); - - mach_accel_out_call(port, val, mach, svga, (ibm8514_t *) svga->dev8514); -} - static uint16_t mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, int len) { @@ -3832,7 +4058,19 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) + temp = mach->accel.cy_end_line; + else + temp = ibm8514_accel_in_fifo(svga, port, len); + break; + case 0x86e8: + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) + temp = mach->accel.cx_end_line; + else + temp = ibm8514_accel_in_fifo(svga, port, len); + break; + case 0x92e8: case 0x96e8: case 0xc2e8: @@ -3842,18 +4080,24 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9ae8: case 0xdae8: - if ((dev->fifo_idx >= 1) && (dev->fifo_idx <= 8)) { - temp |= (1 << (dev->fifo_idx - 1)); - dev->fifo_idx = 0; - } - if (len == 2) { - if (dev->force_busy) - temp |= 0x200; /*Hardware busy*/ + if (dev->fifo_idx <= 8) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (7 - (i - 1))); + } else + temp = 0x00ff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; + + if (dev->force_busy) + temp |= 0x0200; /*Hardware busy*/ + + if (dev->accel.cmd_back) + dev->force_busy = 0; - dev->force_busy = 0; if (dev->data_available) { - temp |= 0x100; /*Read Data available*/ + temp |= 0x0100; /*Read Data available*/ if (mach->accel.cmd_type >= 0) { switch (mach->accel.cmd_type) { case 2: @@ -3891,10 +4135,13 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9ae9: case 0xdae9: if (len == 1) { + dev->fifo_idx = 0; + if (dev->force_busy2) temp |= 0x02; /*Hardware busy*/ dev->force_busy2 = 0; + if (dev->data_available2) { temp |= 0x01; /*Read Data available*/ if (mach->accel.cmd_type >= 0) { @@ -3913,8 +4160,19 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; } } else { - if (dev->accel.sy < 0) - dev->data_available2 = 0; + switch (dev->accel.cmd >> 13) { + case 2: + case 3: + case 4: + case 6: + if (dev->accel.sy < 0) + dev->data_available = 0; + break; + default: + if (!dev->accel.sy) + dev->data_available = 0; + break; + } } } } @@ -3930,7 +4188,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in READ_PIXTRANS_BYTE_IO(dev->accel.dx, 1) temp = mach->accel.pix_trans[1]; } else { - if (mach->accel.cmd_type == 3) { + if ((mach->accel.cmd_type == 3) || (mach->accel.cmd_type == 4)) { READ_PIXTRANS_WORD(dev->accel.cx, 0) } else { READ_PIXTRANS_WORD(dev->accel.dx, 0) @@ -3943,7 +4201,7 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in cmd = (dev->accel.cmd >> 13); if (len == 2) { READ_PIXTRANS_WORD(dev->accel.cx, 0) - if (dev->subsys_stat & 0x01) { + if (dev->subsys_stat & INT_VSY) { dev->force_busy = 1; dev->data_available = 1; } @@ -4017,10 +4275,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x8eee: - if (len == 1) - temp = mach->accel.ext_ge_config & 0xff; - else + if (len == 2) temp = mach->accel.ext_ge_config; + else + temp = mach->accel.ext_ge_config & 0xff; mach_log("ExtGE Read = %04x, len=%d.\n", temp, len); break; @@ -4030,10 +4288,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x92ee: - if (len == 1) - temp = mach->accel.eeprom_control & 0xff; - else + if (len == 2) temp = mach->accel.eeprom_control; + else + temp = mach->accel.eeprom_control & 0xff; mach_log("EEPROM cntl read=%04x, len=%d.\n", temp, len); break; @@ -4045,10 +4303,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0x96ee: - if (len == 1) - temp = mach->accel.test & 0xff; - else + if (len == 2) temp = mach->accel.test; + else + temp = mach->accel.test & 0xff; break; case 0x96ef: if (len == 1) @@ -4057,18 +4315,22 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x9aee: if (len == 2) { - if ((dev->ext_fifo_idx >= 1) && (dev->ext_fifo_idx <= 16)) { - temp |= (1 << (dev->ext_fifo_idx - 1)); - dev->ext_fifo_idx = 0; - } + if (dev->fifo_idx <= 16) { + for (int i = 1; i <= dev->fifo_idx; i++) + temp |= (1 << (15 - (i - 1))); + } else + temp = 0xffff; + + if (dev->fifo_idx > 0) + dev->fifo_idx--; } break; case 0xa2ee: - if (len == 1) - temp = mach->accel.linedraw_opt & 0xff; - else + if (len == 2) temp = mach->accel.linedraw_opt; + else + temp = mach->accel.linedraw_opt & 0xff; break; case 0xa2ef: if (len == 1) @@ -4076,11 +4338,11 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xb2ee: - if (len == 1) - temp = dev->hdisped; - else { + if (len == 2) { temp = dev->hdisped & 0xff; temp |= (dev->htotal << 8); + } else { + temp = dev->hdisped; } mach_log("B2EE read=%02x.\n", temp & 0xff); break; @@ -4098,12 +4360,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xc2ee: - if (len == 1) - temp = dev->v_total_reg & 0xff; - else { + if (len == 2) temp = dev->v_total_reg; - mach_log("VTOTAL read=%d.\n", temp); - } + else + temp = dev->v_total_reg & 0xff; break; case 0xc2ef: if (len == 1) @@ -4111,12 +4371,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xc6ee: - if (len == 1) - temp = dev->v_disp & 0xff; - else { + if (len == 2) temp = dev->v_disp; - mach_log("VDISP read=%d.\n", temp); - } + else + temp = dev->v_disp & 0xff; break; case 0xc6ef: if (len == 1) @@ -4124,10 +4382,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in break; case 0xcaee: - if (len == 1) - temp = dev->v_sync_start & 0xff; - else + if (len == 2) temp = dev->v_sync_start; + else + temp = dev->v_sync_start & 0xff; break; case 0xcaef: if (len == 1) @@ -4136,10 +4394,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xceee: mach_log("CEEE read=%d.\n", len); - if (len == 1) - temp = dev->vc & 0xff; - else + if (len == 2) temp = dev->vc & 0x7ff; + else + temp = dev->vc & 0xff; break; case 0xceef: mach_log("CEEF read=%d.\n", len); @@ -4167,8 +4425,10 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in if (len == 2) { if ((dev->local & 0xff) >= 0x02) temp = mach->accel.src_y; - } else - temp = mach->accel.src_y & 0xff; + } else { + if ((dev->local & 0xff) >= 0x02) + temp = mach->accel.src_y & 0xff; + } break; case 0xdeef: if (len == 1) { @@ -4218,6 +4478,7 @@ static uint8_t mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { uint8_t temp = 0; + uint8_t fifo_test_tag[16] = { 0x7c, 0x64, 0x60, 0x5c, 0x58, 0x54, 0x50, 0x68, 0x38, 0x24, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x4c}; int16_t clip_t = dev->accel.clip_top; int16_t clip_l = dev->accel.clip_left; int16_t clip_b = dev->accel.clip_bottom; @@ -4240,63 +4501,64 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x42e8: case 0x42e9: - if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) - temp |= 0x01; + if (!(port & 1)) { + if ((dev->subsys_cntl & INT_VSY) && !(dev->subsys_stat & INT_VSY) && (dev->vc == dev->dispend)) + temp |= INT_VSY; - if (mach->accel.cmd_type == -1) { - if (cmd == 6) { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r_ibm) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b_ibm)) - temp |= 0x02; - } else { - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r_ibm) && - (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b_ibm)) - temp |= 0x02; - } - } else { - switch (mach->accel.cmd_type) { - case 1: - case 2: - case 5: - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && - (dev->accel.dx >= clip_l) && - (dev->accel.dx <= clip_r) && - (dev->accel.dy >= clip_t) && - (dev->accel.dy <= clip_b)) - temp |= 0x02; - break; - case 3: - case 4: - if ((dev->subsys_cntl & 0x02) && - !(dev->subsys_stat & 0x02) && + if (mach->accel.cmd_type == -1) { + if (cmd == 6) { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx_ibm >= clip_l) && + (dev->accel.dx_ibm <= clip_r_ibm) && + (dev->accel.dy_ibm >= clip_t) && + (dev->accel.dy_ibm <= clip_b_ibm)) + temp |= INT_GE_BSY; + } else { + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && (dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r) && + (dev->accel.cx <= clip_r_ibm) && (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b)) - temp |= 0x02; - break; - default: - break; + (dev->accel.cy <= clip_b_ibm)) + temp |= INT_GE_BSY; + } + } else { + switch (mach->accel.cmd_type) { + case 1: + case 2: + case 5: + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.dx >= clip_l) && + (dev->accel.dx <= clip_r) && + (dev->accel.dy >= clip_t) && + (dev->accel.dy <= clip_b)) + temp |= INT_GE_BSY; + break; + case 3: + case 4: + if ((dev->subsys_cntl & INT_GE_BSY) && + !(dev->subsys_stat & INT_GE_BSY) && + (dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b)) + temp |= INT_GE_BSY; + break; + default: + break; + } } - } - if ((!dev->fifo_idx || !dev->ext_fifo_idx)) { - if ((!dev->force_busy && !dev->force_busy2) || !mach->force_busy) - temp |= 0x08; - } - if (port & 1) { - temp = dev->vram_512k_8514 ? 0x00 : 0x80; - temp |= (dev->subsys_cntl >> 8); - } else { + if (dev->accel.cmd_back) { + dev->force_busy = 0; + dev->force_busy2 = 0; + mach->force_busy = 0; + dev->data_available = 0; + dev->data_available2 = 0; + temp |= INT_FIFO_EMP; + } temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); @@ -4318,8 +4580,16 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) break; case 0x1aee: + if (dev->fifo_idx > 0) + dev->fifo_idx--; + if (mach->fifo_test_idx > 0) + mach->fifo_test_idx--; + fallthrough; case 0x1aef: - temp = 0x00; + mach_log("FIFO Test IDX=%d, Data=%04x.\n", mach->fifo_test_idx, mach->fifo_test_data[mach->fifo_test_idx]); + READ8(port, mach->fifo_test_data[mach->fifo_test_idx]); + if (!mach->fifo_test_idx && ((mach->accel.dp_config == 0xaaaa) || (mach->accel.dp_config == 0x5555))) + mach->accel.dp_config = 0x2211; break; case 0x22ee: @@ -4336,7 +4606,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x36ef: if ((dev->local & 0xff) >= 0x02) { READ8(port, mach->misc); - if (!(port & 1)) { temp &= ~0x0c; switch (dev->vram_amount) { @@ -4357,6 +4626,14 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) } break; + case 0x3aee: + case 0x3aef: + if (port & 1) + temp = 0x01; + else + temp = fifo_test_tag[dev->fifo_idx]; + break; + case 0x42ee: case 0x42ef: READ8(port, mach->accel.test2); @@ -4380,7 +4657,13 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) temp = (((dev->bios_rom.mapping.base >> 7) - 0x1000) >> 4); if (port & 1) temp |= 0x01; + } else { + if (mach->accel.scratch0 == 0x1234) + temp = 0x0000; } + } else { + if (mach->accel.scratch0 == 0x1234) + temp = 0x0000; } break; @@ -4440,30 +4723,30 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - if (port == 0x2ee8 || port == 0x2ee9 || port == 0x42e8 || port == 0x42e9) - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } -static void -ati8514_accel_out(uint16_t port, uint8_t val, svga_t *svga) -{ - mach_log("[%04X:%08X]: Port NORMAL OUT=%04x, val=%04x.\n", CS, cpu_state.pc, port, val); - - mach_accel_out_call(port, val, (mach_t *)svga->ext8514, svga, (ibm8514_t *) svga->dev8514); -} - static void ati8514_accel_outb(uint16_t port, uint8_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); - else - ati8514_accel_out(port, val, svga); + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } + } + dev->accel_out_fifo(svga, port, val, 1); + mach_log("%04X:%08X: OUTB port=%04x, val=%02x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4471,13 +4754,23 @@ ati8514_accel_outw(uint16_t port, uint16_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); - else { - ati8514_accel_out(port, val, svga); - ati8514_accel_out(port + 1, (val >> 8), svga); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(svga, port, val, 2); + mach_log("%04X:%08X: OUTW port=%04x, val=%04x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4485,16 +4778,23 @@ ati8514_accel_outl(uint16_t port, uint32_t val, void *priv) { svga_t *svga = (svga_t *)priv; mach_t *mach = (mach_t *)svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) { - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); - } else { - ati8514_accel_out(port, val, svga); - ati8514_accel_out(port + 1, (val >> 8), svga); - ati8514_accel_out(port + 2, (val >> 16), svga); - ati8514_accel_out(port + 3, (val >> 24), svga); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(svga, port, val, 2); + mach_log("OUTL port=%04x, val=%08x, fifo idx=%d.\n", port, val, dev->fifo_idx); } static void @@ -4502,11 +4802,20 @@ mach_accel_outb(uint16_t port, uint8_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 1); - else - mach_accel_out(port, val, mach); + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } + } + dev->accel_out_fifo(mach, port, val, 1); + mach_log("%04X:%08X: OUTB port=%04x, val=%02x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4514,13 +4823,23 @@ mach_accel_outw(uint16_t port, uint16_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val, 2); - else { - mach_accel_out(port, val, mach); - mach_accel_out(port + 1, (val >> 8), mach); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(mach, port, val, 2); + mach_log("%04X:%08X: OUTW port=%04x, val=%04x, fifo idx=%d.\n", CS, cpu_state.pc, port, val, dev->fifo_idx); } static void @@ -4528,16 +4847,23 @@ mach_accel_outl(uint16_t port, uint32_t val, void *priv) { mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - if (port & 0x8000) { - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, val & 0xffff, 2); - mach_accel_out_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, val >> 16, 2); - } else { - mach_accel_out(port, val, mach); - mach_accel_out(port + 1, (val >> 8), mach); - mach_accel_out(port + 2, (val >> 16), mach); - mach_accel_out(port + 3, (val >> 24), mach); + if (port == 0xf6ee) + port = 0x82e8; + + if (port & 0x8000) { /*Command FIFO*/ + if (dev->accel.cmd_back) { + mach->fifo_test_data[dev->fifo_idx] = val; + dev->fifo_idx++; + if (dev->fifo_idx > 16) + dev->fifo_idx = 16; + + mach->fifo_test_idx = dev->fifo_idx; + } } + dev->accel_out_fifo(mach, port, val, 2); + mach_log("OUTL port=%04x, val=%08x, fifo idx=%d.\n", port, val, dev->fifo_idx); } static uint8_t @@ -4558,6 +4884,7 @@ ati8514_accel_inb(uint16_t port, void *priv) else temp = ati8514_accel_in(port, svga); + mach_log("%04X:%08X: INB port=%04x, temp=%02x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4574,6 +4901,8 @@ ati8514_accel_inw(uint16_t port, void *priv) temp = ati8514_accel_in(port, svga); temp |= (ati8514_accel_in(port + 1, svga) << 8); } + + mach_log("%04X:%08X: INW port=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4584,14 +4913,11 @@ ati8514_accel_inl(uint16_t port, void *priv) mach_t *mach = (mach_t *)svga->ext8514; uint32_t temp; - if (port & 0x8000) { + if (port & 0x8000) temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); - temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); - } else { + else { temp = ati8514_accel_in(port, svga); temp |= (ati8514_accel_in(port + 1, svga) << 8); - temp |= (ati8514_accel_in(port + 2, svga) << 16); - temp |= (ati8514_accel_in(port + 3, svga) << 24); } return temp; } @@ -4615,6 +4941,7 @@ mach_accel_inb(uint16_t port, void *priv) else temp = mach_accel_in(port, mach); + mach_log("%04X:%08X: INB port=%04x, temp=%02x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4631,6 +4958,8 @@ mach_accel_inw(uint16_t port, void *priv) temp = mach_accel_in(port, mach); temp |= (mach_accel_in(port + 1, mach) << 8); } + + mach_log("%04X:%08X: INW port=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -4641,14 +4970,11 @@ mach_accel_inl(uint16_t port, void *priv) svga_t *svga = &mach->svga; uint32_t temp; - if (port & 0x8000) { + if (port & 0x8000) temp = mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port, 2); - temp = (mach_accel_in_fifo(mach, svga, (ibm8514_t *) svga->dev8514, port + 2, 2) << 16); - } else { + else { temp = mach_accel_in(port, mach); temp |= (mach_accel_in(port + 1, mach) << 8); - temp |= (mach_accel_in(port + 2, mach) << 16); - temp |= (mach_accel_in(port + 3, mach) << 24); } return temp; } @@ -4817,6 +5143,11 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; switch (addr & 0x06) { @@ -4838,6 +5169,8 @@ mach32_write(uint32_t addr, uint8_t val, void *priv) } } else mach32_write_common(addr, val, 0, mach, svga); + + mach_log("Writeb banked=%08x.\n", addr); } static void @@ -4850,6 +5183,11 @@ mach32_writew(uint32_t addr, uint16_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; if (addr & 0x04) { @@ -4867,6 +5205,7 @@ mach32_writew(uint32_t addr, uint16_t val, void *priv) mach32_write_common(addr, val & 0xff, 0, mach, svga); mach32_write_common(addr + 1, val >> 8, 0, mach, svga); } + mach_log("Writew banked=%08x.\n", addr); } static void @@ -4879,6 +5218,11 @@ mach32_writel(uint32_t addr, uint32_t val, void *priv) xga_write_test(addr, val, svga); addr = (addr & svga->banked_mask) + svga->write_bank; + if (mach->accel.test2 & 0x10) { + if (addr < ((mach->accel.test2 & 0x0f) << 18)) + return; + } + if ((((dev->local & 0xff) >= 0x02) && !dev->vram_512k_8514) && ((mach->accel.ext_ge_config & 0x30) == 0x00)) { addr <<= 1; mach32_write_common(addr, val & 0x0f, 0, mach, svga); @@ -4895,6 +5239,223 @@ mach32_writel(uint32_t addr, uint32_t val, void *priv) mach32_write_common(addr + 2, val >> 16, 0, mach, svga); mach32_write_common(addr + 3, val >> 24, 0, mach, svga); } + + mach_log("Writel banked=%08x.\n", addr); +} + +static __inline void +mach32_svga_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + int writemask2 = svga->writemask; + int reset_wm = 0; + latch_t vall; + uint8_t wm = svga->writemask; + uint8_t count; + uint8_t i; + + cycles -= svga->monitor->mon_video_timing_write_b; + + xga_write_test(addr, val, svga); + addr = svga_decode_addr(svga, addr, 1); + if (addr == 0xffffffff) { + mach_log("WriteCommon Over.\n"); + return; + } + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if (((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain4 && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) { + mach_log("WriteBankedOver=%08x, val=%02x.\n", addr & svga->vram_mask, val); + return; + } + + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + + count = 4; + + switch (svga->writemode) { + case 0: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = val; + } + return; + } else { + for (i = 0; i < count; i++) { + if (svga->gdcreg[1] & (1 << i)) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + else + vall.b[i] = val; + } + } + break; + case 1: + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = svga->latch.b[i]; + } + return; + case 2: + for (i = 0; i < count; i++) + vall.b[i] = !!(val & (1 << i)) * 0xff; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + return; + } + break; + case 3: + val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); + wm = svga->gdcreg[8]; + svga->gdcreg[8] &= val; + + for (i = 0; i < count; i++) + vall.b[i] = !!(svga->gdcreg[0] & (1 << i)) * 0xff; + + reset_wm = 1; + break; + default: + return; + } + + switch (svga->gdcreg[3] & 0x18) { + case 0x00: /* Set */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | (svga->latch.b[i] & ~svga->gdcreg[8]); + } + break; + case 0x08: /* AND */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] | ~svga->gdcreg[8]) & svga->latch.b[i]; + } + break; + case 0x10: /* OR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) | svga->latch.b[i]; + } + break; + case 0x18: /* XOR */ + for (i = 0; i < count; i++) { + if (writemask2 & (1 << i)) + svga->vram[addr | i] = (vall.b[i] & svga->gdcreg[8]) ^ svga->latch.b[i]; + } + break; + + default: + break; + } + + if (reset_wm) + svga->gdcreg[8] = wm; +} + +static __inline void +mach32_svga_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + if (!svga->fast) { + mach32_svga_write(addr, val, priv); + mach32_svga_write(addr + 1, val >> 8, priv); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_w; + + xga_write_test(addr, val & 0xff, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint16_t *) &svga->vram[addr] = val; +} + +static __inline void +mach32_svga_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + if (!svga->fast) { + mach32_svga_write(addr, val, priv); + mach32_svga_write(addr + 1, val >> 8, priv); + mach32_svga_write(addr + 2, val >> 16, priv); + mach32_svga_write(addr + 3, val >> 24, priv); + return; + } + + cycles -= svga->monitor->mon_video_timing_write_l; + + xga_write_test(addr, val & 0xff, svga); + xga_write_test(addr + 1, (val >> 8) & 0xff, svga); + xga_write_test(addr + 2, (val >> 16) & 0xff, svga); + xga_write_test(addr + 3, (val >> 24) & 0xff, svga); + addr = svga_decode_addr(svga, addr, 1); + + if (addr == 0xffffffff) + return; + + if (mach->accel.test2 & 0x10) { + if (addr >= ((mach->accel.test2 & 0x0f) << 18)) + return; + } + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; + *(uint32_t *) &svga->vram[addr] = val; } static __inline void @@ -5100,6 +5661,7 @@ mach32_read(uint32_t addr, void *priv) } else ret = mach32_read_common(addr, 0, mach, svga); + mach_log("Readb banked=%08x.\n", addr); return ret; } @@ -5131,6 +5693,7 @@ mach32_readw(uint32_t addr, void *priv) ret = mach32_read_common(addr, 0, mach, svga); ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 8); } + mach_log("Readw banked=%08x.\n", addr); return ret; } @@ -5161,6 +5724,7 @@ mach32_readl(uint32_t addr, void *priv) ret |= (mach32_read_common(addr + 2, 0, mach, svga) << 16); ret |= (mach32_read_common(addr + 3, 0, mach, svga) << 24); } + mach_log("Readl banked=%08x.\n", addr); return ret; } @@ -5224,19 +5788,22 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (addr & 1) + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (addr & 1) + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); + mach_log("Port WORDB Write=%04x.\n", actual_port_ext); + mach_accel_outb(actual_port_ext, val, mach); } else { - mach_log("Port WORDB Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outb(0x02e8 + (addr & 1) + (port_dword << 8), val, mach); + mach_log("Port WORDB Write=%04x.\n", actual_port); + mach_accel_outb(actual_port, val, mach); } } else { mach_log("Linear WORDB Write=%08x, val=%02x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + if (dev->on) mach32_write_common(addr, val, 1, mach, svga); else @@ -5251,19 +5818,21 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outw(0x02ee + (port_dword << 8), val, mach); + mach_log("Port WORDW Write=%04x, localcntl=%02x, pcicntl=%02x, actual addr=%08x, val=%04x.\n", actual_port_ext, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr, val); + mach_accel_outw(actual_port_ext, val, mach); } else { - mach_log("Port WORDW Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outw(0x02e8 + (port_dword << 8), val, mach); + mach_log("Port WORDW Write=%04x, localcntl=%02x, pcicntl=%02x, actual addr=%08x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80, addr); + mach_accel_outw(actual_port, val, mach); } } else { - mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x, base=%08x, 8514/A port=%04x, ATI port=%04x, switch=%03x.\n", + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20, mach->linear_base, actual_port, actual_port_ext, addr & 0x100); if (dev->on) mach32_writew_linear(addr, val, mach); else @@ -5278,6 +5847,8 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); @@ -5285,13 +5856,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - mach_log("Port WORDL Write=%04x.\n", 0x02ee + (port_dword << 8)); - mach_accel_outw(0x02ee + (port_dword << 8), val & 0xffff, mach); - mach_accel_outw(0x02ee + (port_dword << 8) + 4, val >> 16, mach); + mach_log("Port WORDL Write=%04x, localcntl=%02x, pcicntl=%02x.\n", actual_port_ext, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80); + mach_accel_outl(actual_port_ext, val, mach); } else { - mach_log("Port WORDL Write=%04x.\n", 0x02e8 + (port_dword << 8)); - mach_accel_outw(0x02e8 + (port_dword << 8), val & 0xffff, mach); - mach_accel_outw(0x02e8 + (port_dword << 8) + 4, val >> 16, mach); + mach_log("Port WORDL Write=%04x, localcntl=%02x, pcicntl=%02x.\n", actual_port, mach->local_cntl & 0x20, mach->pci_cntl_reg & 0x80); + mach_accel_outl(actual_port, val, mach); } } else { if (dev->on) @@ -5309,13 +5878,15 @@ mach32_ap_readb(uint32_t addr, void *priv) const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (addr & 1) + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (addr & 1) + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) - temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); + temp = mach_accel_inb(actual_port_ext, mach); else - temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); + temp = mach_accel_inb(actual_port, mach); } else { if (dev->on) temp = mach32_read_common(addr, 1, mach, svga); @@ -5335,14 +5906,19 @@ mach32_ap_readw(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint16_t temp; - uint8_t port_dword = (addr - mach->linear_base) & 0xfc; + uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { - if (addr & 0x100) - temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); - else - temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); + if (addr & 0x100) { + temp = mach_accel_inw(actual_port_ext, mach); + mach_log("Port WORDW Read=%04x.\n", actual_port_ext); + } else { + temp = mach_accel_inw(actual_port, mach); + mach_log("Port WORDW Read=%04x.\n", actual_port); + } } else { if (dev->on) temp = mach32_readw_linear(addr, mach); @@ -5363,15 +5939,17 @@ mach32_ap_readl(uint32_t addr, void *priv) const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; uint8_t port_dword = addr & 0xfc; + uint16_t actual_port = 0x02e8 + (port_dword << 8); + uint16_t actual_port_ext = 0x02ee + (port_dword << 8); if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { if (addr & 0x100) { - temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); - temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); + temp = mach_accel_inl(actual_port_ext, mach); + mach_log("Port WORDL Read=%04x.\n", actual_port_ext); } else { - temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); - temp |= (mach_accel_inw(0x02e8 + (port_dword << 8) + 4, mach) << 8); + temp = mach_accel_inl(actual_port, mach); + mach_log("Port WORDL Read=%04x.\n", actual_port); } } else { if (dev->on) @@ -5405,14 +5983,17 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; + mem_mapping_set_addr(&mach->banked_mapping, 0xa0000, 0x20000); break; case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; + mem_mapping_set_addr(&mach->banked_mapping, 0xa0000, 0x10000); break; case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; + mem_mapping_set_addr(&mach->banked_mapping, 0xb0000, 0x08000); break; case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); @@ -5426,6 +6007,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) } } } + mem_mapping_set_addr(&mach->banked_mapping, 0xb8000, 0x08000); break; default: @@ -5433,7 +6015,7 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) } } - mach_log("Linear base = %08x, aperture = %04x, localcntl = %02x svgagdc = %x.\n", + mach_log("Linear base=%08x, aperture=%04x, localcntl=%02x, svgagdc=%x.\n", mach->linear_base, mach->memory_aperture, mach->local_cntl, svga->gdcreg[6] & 0x0c); if (mach->linear_base) { if (((mach->memory_aperture & 3) == 1) && !mach->pci_bus) { @@ -5452,24 +6034,20 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) mach_log("Linear Disabled APSIZE=4.\n"); mem_mapping_disable(&mach->mmio_linear_mapping); } + if ((dev->local & 0xff) >= 0x02) { if (dev->on && dev->vendor_mode) { mach_log("Mach32 banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); - mem_mapping_set_p(&svga->mapping, mach); + mem_mapping_disable(&svga->mapping); + mem_mapping_enable(&mach->banked_mapping); } else { - if (!dev->on) { - memset(dev->vram, 0, dev->vram_size); - memset(dev->changedvram, 0, (dev->vram_size >> 12) + 1); - } mach_log("IBM compatible banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&svga->mapping, svga); + mem_mapping_enable(&svga->mapping); + mem_mapping_disable(&mach->banked_mapping); } } else { - mach_log("IBM compatible banked mapping.\n"); - mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&svga->mapping, svga); + mem_mapping_enable(&svga->mapping); + mem_mapping_disable(&mach->banked_mapping); } } @@ -5869,6 +6447,7 @@ mach_io_set(mach_t *mach) io_sethandler(0x7eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x82ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x86ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x8aee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x8eee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x92ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x96ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -5891,6 +6470,7 @@ mach_io_set(mach_t *mach) io_sethandler(0xdeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xe2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xe6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xeaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -6122,6 +6702,95 @@ mach32_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) } } +static void +mach_vblank_start(mach_t *mach, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + dev->subsys_stat |= INT_VSY; +} + +static void +mach_combo_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->priv; + + mach_vblank_start(mach, svga); +} + +static void +ati8514_vblank_start(void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + + mach_vblank_start(mach, svga); +} + +static void +mach_combo_accel_out_fifo(void *priv, uint16_t port, uint16_t val, int len) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_log("Accel OUT Combo=%04x, val=%04x, len=%d.\n", port, val, len); + mach_accel_out_fifo(mach, svga, dev, port, val, len); +} + +static void +ati8514_accel_out_fifo(void *priv, uint16_t port, uint16_t val, int len) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + mach_accel_out_fifo(mach, svga, dev, port, val, len); +} + +static void +mach_disable_handlers(mach_t *mach) +{ + io_removehandler(0x01ce, 2, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x02ea, 4, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + io_removehandler(0x03c0, 32, mach_in, NULL, NULL, mach_out, NULL, NULL, mach); + mach_io_remove(mach); + + mem_mapping_disable(&mach->mmio_linear_mapping); + mem_mapping_disable(&mach->banked_mapping); + mem_mapping_disable(&mach->svga.mapping); + if (mach->pci_bus && mach->has_bios) + mem_mapping_disable(&mach->bios_rom.mapping); + + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->mmio_linear_mapping = mach->mmio_linear_mapping; + reset_state->banked_mapping = mach->banked_mapping; + reset_state->svga.mapping = mach->svga.mapping; + reset_state->bios_rom.mapping = mach->bios_rom.mapping; + + reset_state->svga.timer = mach->svga.timer; +} + +static void +mach_reset(void *priv) +{ + mach_t *mach = (mach_t *) priv; + svga_t *svga = &mach->svga; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + + if (reset_state != NULL) { + mach_disable_handlers(mach); + mach->force_busy = 0; + dev->force_busy = 0; + dev->force_busy2 = 0; + if (mach->pci_bus) + reset_state->pci_slot = mach->pci_slot; + + *mach = *reset_state; + } +} + static void * mach8_init(const device_t *info) { @@ -6130,6 +6799,7 @@ mach8_init(const device_t *info) ibm8514_t *dev; mach = calloc(1, sizeof(mach_t)); + reset_state = calloc(1, sizeof(mach_t)); svga = &mach->svga; dev = (ibm8514_t *) calloc(1, sizeof(ibm8514_t)); @@ -6145,6 +6815,7 @@ mach8_init(const device_t *info) mach->ramdac_type = mach->pci_bus ? device_get_config_int("ramdac") : 1; dev->vram_amount = device_get_config_int("memory"); dev->vram_512k_8514 = dev->vram_amount == 512; + dev->accel.cmd_back = 1; if ((dev->local & 0xff) >= 0x02) { if (mach->pci_bus) { @@ -6227,8 +6898,12 @@ mach8_init(const device_t *info) mach->config1 |= 0x0400; svga->clock_gen = device_add(&ati18811_1_device); } + mem_mapping_add(&mach->banked_mapping, 0, 0, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel, NULL, MEM_MAPPING_EXTERNAL, mach); mem_mapping_add(&mach->mmio_linear_mapping, 0, 0, mach32_ap_readb, mach32_ap_readw, mach32_ap_readl, mach32_ap_writeb, mach32_ap_writew, mach32_ap_writel, NULL, MEM_MAPPING_EXTERNAL, mach); + mem_mapping_disable(&mach->banked_mapping); mem_mapping_disable(&mach->mmio_linear_mapping); + + mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, mach32_svga_write, mach32_svga_writew, mach32_svga_writel); } else { svga_init(info, svga, mach, (512 << 10), /*default: 512kB VGA for 28800-6 + 1MB for Mach8*/ mach_recalctimings, @@ -6240,7 +6915,7 @@ mach8_init(const device_t *info) dev->changedvram = calloc((dev->vram_size >> 12) + 1, 1); dev->vram_mask = dev->vram_size - 1; video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); - mach->config1 = 0x01 | 0x02 | 0x08 | 0x80; + mach->config1 = 0x01 | 0x08 | 0x80; if (dev->vram_amount >= 1024) mach->config1 |= 0x20; @@ -6296,6 +6971,11 @@ mach8_init(const device_t *info) } else ati_eeprom_load_mach8_vga(&mach->eeprom, "mach8.nvr"); + dev->accel_out_fifo = mach_combo_accel_out_fifo; + dev->vblank_start = mach_combo_vblank_start; + + *reset_state = *mach; + return mach; } @@ -6315,9 +6995,11 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) io_sethandler(0x02ea, 4, ati8514_in, NULL, NULL, ati8514_out, NULL, NULL, svga); ati8514_io_set(svga); + mach->accel.cmd_type = -2; mach->mca_bus = !!(dev->type & DEVICE_MCA); + dev->accel.cmd_back = 1; - mach->config1 = 0x02 | 0x08 | 0x80; + mach->config1 = 0x08 | 0x80; if (mach->mca_bus) mach->config1 |= 0x04; @@ -6326,6 +7008,9 @@ ati8514_init(svga_t *svga, void *ext8514, void *dev8514) mach->config1 |= 0x20; mach->config2 = 0x01 | 0x02; + + dev->accel_out_fifo = ati8514_accel_out_fifo; + dev->vblank_start = ati8514_vblank_start; } static int @@ -6373,6 +7058,10 @@ mach_close(void *priv) } svga_close(svga); + + free(reset_state); + reset_state = NULL; + free(mach); } @@ -6479,7 +7168,7 @@ const device_t mach8_vga_isa_device = { .local = 1, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach8_vga_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6493,7 +7182,7 @@ const device_t mach32_isa_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_isa_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6507,7 +7196,7 @@ const device_t mach32_vlb_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_vlb_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6521,7 +7210,7 @@ const device_t mach32_mca_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_mca_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6535,7 +7224,7 @@ const device_t mach32_pci_device = { .local = 2, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = mach32_pci_available, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, @@ -6549,7 +7238,7 @@ const device_t mach32_onboard_pci_device = { .local = 2 | 0x100, .init = mach8_init, .close = mach_close, - .reset = NULL, + .reset = mach_reset, .available = NULL, .speed_changed = mach_speed_changed, .force_redraw = mach_force_redraw, From 1c98437e664918c05e66e4d664ae061fc0374bb0 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 29 Mar 2025 14:49:13 +0100 Subject: [PATCH 158/158] More display changes. SVGA related: If CRTC1/HDISP is odd (if bit 0 is set), then make it even accordingly, else leave it as is. Should fix some display skews. S3 related: Remove old code references (can still be accessed through history if one needs it). 8514/A compatible related: Proper use of the htotal and hdisp timings. --- src/video/vid_s3.c | 177 +------------------------------------------ src/video/vid_svga.c | 10 ++- 2 files changed, 8 insertions(+), 179 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 769cd0001..ef21b18df 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -3519,34 +3519,6 @@ s3_recalctimings(svga_t *svga) } } -#ifdef OLD_CODE_REFERENCE - if (s3->card_type == S3_MIROCRYSTAL10SD_805 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_MIROCRYSTAL8S_805 || s3->card_type == S3_NUMBER9_9FX_531 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (!(svga->crtc[0x5e] & 0x04)) - svga->vblankstart = svga->dispend; - if (svga->bpp != 32) { - if (svga->crtc[0x31] & 2) - s3->width = 2048; - else { - if (s3->card_type == S3_MIROCRYSTAL10SD_805) { - if (svga->hdisp == 1280 && s3->width == 1024) { - s3->width = 1280; - } - } - } - } else { - if (s3->card_type == S3_NUMBER9_9FX_531) { - if ((svga->hdisp == 1600) && (s3->width == 1600)) - s3->width = 800; - } - } - } else if (s3->chip == S3_86C928) { - if (svga->bpp == 15) { - if (s3->width == 800) - s3->width = 1024; - } - } -#endif - if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], @@ -3665,29 +3637,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if (s3->chip != S3_VISION868) { - if (s3->chip == S3_86C928) { - if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600) { - if ((s3->width != 1600) && (svga->dispend == 1024) && (svga->hdisp != 1280)) - svga->hdisp <<= 2; - else - svga->hdisp <<= 1; - } - } else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } else if (s3->card_type == S3_SPEA_MERCURY_P64V) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } - } else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } -#endif break; case 15: svga->render = svga_render_15bpp_highres; @@ -3856,29 +3805,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408 * 2)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; -#endif break; case 16: svga->render = svga_render_16bpp_highres; @@ -4044,35 +3970,6 @@ s3_recalctimings(svga_t *svga) default: break; } - -#ifdef OLD_CODE_REFERENCE - if ((s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->card_type == S3_ELSAWIN2KPROX)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - } - if ((s3->chip != S3_VISION964) && (s3->card_type != S3_SPEA_MIRAGE_86C801) && (s3->card_type != S3_SPEA_MIRAGE_86C805)) { - if (s3->chip == S3_86C928) - svga->hdisp <<= 1; - else if (s3->chip != S3_VISION968) - svga->hdisp >>= 1; - } else if ((s3->card_type == S3_SPEA_MIRAGE_86C801) || (s3->card_type == S3_SPEA_MIRAGE_86C805)) - svga->hdisp >>= 1; - if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) { - if (s3->width == 1280 || s3->width == 1600) - svga->hdisp <<= 1; - else if (s3->card_type == S3_NUMBER9_9FX_771) - svga->hdisp <<= 1; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - if (svga->hdisp == (1408 << 1)) - svga->hdisp >>= 1; - else - svga->hdisp = s3->width; - } - - if (s3->card_type == S3_SPEA_MIRAGE_86C801 || s3->card_type == S3_SPEA_MIRAGE_86C805 || s3->card_type == S3_SPEA_MERCURY_LITE_PCI) - svga->hdisp = s3->width; -#endif break; case 24: svga->render = svga_render_24bpp_highres; @@ -4150,34 +4047,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if (s3->chip != S3_VISION968) { - if (s3->chip != S3_86C928 && s3->chip != S3_86C801 && s3->chip != S3_86C805) - svga->hdisp /= 3; - else - svga->hdisp = (svga->hdisp * 2) / 3; - - if (s3->card_type == S3_SPEA_MERCURY_LITE_PCI) { - if (s3->width == 2048) { - switch (svga->dispend) { - case 480: - svga->hdisp = 640; - break; - - default: - break; - } - } - } else if (s3->chip == S3_86C924) { - if (svga->dispend == 480) - svga->hdisp = 640; - } - } else { - if ((s3->card_type == S3_MIROVIDEO40SV_ERGO_968) || - (s3->card_type == S3_PHOENIX_VISION968) || (s3->card_type == S3_SPEA_MERCURY_P64V)) - svga->hdisp = s3->width; - } -#endif break; case 32: svga->render = svga_render_32bpp_highres; @@ -4262,48 +4131,6 @@ s3_recalctimings(svga_t *svga) default: break; } -#ifdef OLD_CODE_REFERENCE - if ((s3->chip < S3_TRIO32) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968) && (s3->chip != S3_86C928)) { - if (s3->chip == S3_VISION868) - svga->hdisp >>= 1; - else - svga->hdisp >>= 2; - } - if (s3->width == 1280 || s3->width == 1600 || (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_NUMBER9_9FX_771)) - svga->hdisp <<= 1; - if (s3->card_type == S3_NUMBER9_9FX_771) { - if (svga->hdisp == 832) - svga->hdisp -= 32; - } - if (s3->card_type == S3_MIROVIDEO40SV_ERGO_968 || s3->card_type == S3_MIROCRYSTAL20SV_964 || s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_SPEA_MERCURY_P64V) { - svga->hdisp = s3->width; - if (s3->card_type == S3_MIROCRYSTAL20SD_864 || s3->card_type == S3_MIROCRYSTAL20SV_964) { - if (s3->width == 800 || s3->width == 1024 || s3->width == 1600) { - switch (svga->dispend) { - case 400: - case 480: - svga->hdisp = 640; - break; - - case 576: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 768; - break; - - case 600: - if (s3->width == 1600) - s3->width = 800; - svga->hdisp = 800; - break; - - default: - break; - } - } - } - } -#endif break; default: @@ -4362,7 +4189,7 @@ s3_trio64v_recalctimings(svga_t *svga) svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { svga->hdisp_time |= 0x100; - svga->hdisp |= 0x100 * svga->dots_per_clock; + svga->hdisp |= (0x100 * svga->dots_per_clock); } if (svga->crtc[0x5e] & 0x01) svga->vtotal |= 0x400; @@ -4681,6 +4508,7 @@ s3_trio64_getclock(int clock, void *priv) return 25175000.0; if (clock == 1) return 28322000.0; + m = svga->seqregs[0x13] + 2; n1 = (svga->seqregs[0x12] & 0x1f) + 2; n2 = ((svga->seqregs[0x12] >> 5) & 0x07); @@ -9523,7 +9351,6 @@ s3_disable_handlers(s3_t *s3) reset_state->bios_rom.mapping = s3->bios_rom.mapping; reset_state->svga.timer = s3->svga.timer; - reset_state->svga.timer8514 = s3->svga.timer8514; memset(s3->svga.vram, 0x00, s3->svga.vram_max + 8); memset(s3->svga.changedvram, 0x00, (s3->svga.vram_max >> 12) + 1); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index c7a65120f..a44838d68 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -739,7 +739,8 @@ svga_recalctimings(svga_t *svga) svga->vblankstart++; svga->hdisp = svga->crtc[1]; - svga->hdisp++; + if (svga->crtc[1] & 1) + svga->hdisp++; svga->htotal = svga->crtc[0]; /* +5 has been verified by Sergi to be correct - +6 must have been an off by one error. */ @@ -944,7 +945,7 @@ svga_recalctimings(svga_t *svga) if (dev->on) { uint32_t dot8514 = dev->h_blankstart; uint32_t adj_dot8514 = dev->h_blankstart; - uint32_t eff_mask8514 = 0x0000003f; + uint32_t eff_mask8514 = 0x0000001f; dev->hblank_sub = 0; while (adj_dot8514 < (dev->h_total << 1)) { @@ -1029,8 +1030,9 @@ svga_recalctimings(svga_t *svga) if (ibm8514_active && (svga->dev8514 != NULL)) { if (dev->on) { - disptime8514 = dev->h_total ? dev->h_total : TIMER_USEC; - _dispontime8514 = dev->hdisped; + disptime8514 = dev->h_total; + _dispontime8514 = (dev->hdisped + 1) * 8; + svga_log("HDISPED 8514=%d, htotal=%02x.\n", (dev->hdisped + 1) << 3, dev->h_total); } }