diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e09b5636f..9e5521cf4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,6 +5,7 @@ _Briefly describe what you are submitting._ Checklist ========= * [ ] Closes #xxx +* [ ] I have tested my changes locally and validated that the functionality works as intended * [ ] I have discussed this with core contributors already * [ ] This pull request requires changes to the ROM set * [ ] I have opened a roms pull request - https://github.com/86Box/roms/pull/changeme/ diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 212bf9ce0..4693890e3 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1211,7 +1211,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0x07: /* Recalibrate */ fdc->rw_drive = fdc->params[0] & 3; - fdc->stat = 0x10 | (1 << real_drive(fdc, fdc->drive)); + fdc->stat = (1 << real_drive(fdc, fdc->drive)); if (!(fdc->flags & FDC_FLAG_PCJR)) fdc->stat |= 0x80; fdc->st0 = fdc->params[0] & 3; @@ -1266,7 +1266,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 0x0f: /* Seek */ fdc->rw_drive = fdc->params[0] & 3; - fdc->stat = 0x10 | (1 << fdc->drive); + fdc->stat = (1 << fdc->drive); if (!(fdc->flags & FDC_FLAG_PCJR)) fdc->stat |= 0x80; fdc->head = 0; /* TODO: See if this is correct. */ diff --git a/src/gdbstub.c b/src/gdbstub.c index cbbf0ede7..6e1e9af26 100644 --- a/src/gdbstub.c +++ b/src/gdbstub.c @@ -879,6 +879,7 @@ e22: /* Read by qwords, then by dwords, then by words, then by bytes. */ i = 0; + cpl_override = 1; if (is386) { for (; i < (k & ~7); i += 8) { *((uint64_t *) buf) = readmemql(j); @@ -900,6 +901,7 @@ e22: buf[0] = readmembl(j++); gdbstub_client_respond_hex(client, buf, 1); } + cpl_override = 0; break; case 'M': /* write memory */ @@ -934,6 +936,7 @@ e22: /* Write by qwords, then by dwords, then by words, then by bytes. */ p = client->packet; i = 0; + cpl_override = 1; if (is386) { for (; i < (k & ~7); i += 8) { writememql(j, *((uint64_t *) p)); @@ -955,6 +958,7 @@ e22: writemembl(j++, p[0]); p++; } + cpl_override = 0; /* Respond positively. */ goto ok; diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8c9055c9b..8c8dc6b91 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -12388,7 +12388,7 @@ const machine_t machines[] = { }, /* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */ { - .name = "[i430FX] NEC PowerMate V", + .name = "[i430FX] NEC PowerMate Vxxx", .internal_name = "powermatev", .type = MACHINE_TYPE_SOCKET5, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -12973,7 +12973,7 @@ const machine_t machines[] = { /* Has a SM(S)C FDC37C932 Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { - .name = "[i430FX] HP Vectra VL 5 Series 4", + .name = "[i430FX] HP Vectra VL 5/xxx Series 4 (Chimay)", .internal_name = "vectra54", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430FX, @@ -15329,7 +15329,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* This has the Phoenix MultiKey KBC firmware on the NSC Suepr I/O chip. */ + /* This has the Phoenix MultiKey KBC firmware on the NSC Super I/O chip. */ { .name = "[i430TX] Packard Bell PB790", .internal_name = "an430tx", @@ -16009,7 +16009,7 @@ const machine_t machines[] = { }, /* M1534c kbc */ { - .name = "[ALi ALADDiN V] Gateway Lucas", + .name = "[ALi ALADDiN V] Gateway Lucas (MSI MS-5185)", .internal_name = "gwlucas", .type = MACHINE_TYPE_SOCKETS7, .chipset = MACHINE_CHIPSET_ALI_ALADDIN_V, diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 954547078..e88bedd90 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -84,6 +84,7 @@ extern bool cpu_thread_running; #include #include #include +#include #include #include #include @@ -171,8 +172,6 @@ extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index); extern MainWindow *main_window; -bool MainWindow::s_adjustingForce43 = false; - MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) @@ -933,11 +932,18 @@ MainWindow::closeEvent(QCloseEvent *event) } } if (window_remember) { - window_w = ui->stackedWidget->width(); - window_h = ui->stackedWidget->height(); + // If maximized, persist the normal (restorable) geometry + const bool wasMax = isMaximized(); + QRect normal = wasMax ? this->normalGeometry() : this->geometry(); + // Save WINDOW size (not the content widget’s 4:3 box) + const int chromeHeight = geometry().height() - ui->stackedWidget->height(); + window_w = normal.width(); + window_h = normal.height() - chromeHeight; + if (window_h < 0) + window_h = 0; if (!QApplication::platformName().contains("wayland")) { - window_x = this->geometry().x(); - window_y = this->geometry().y(); + window_x = normal.x(); + window_y = normal.y(); } for (int i = 1; i < MONITORS_NUM; i++) { if (renderers[i]) { @@ -1021,65 +1027,56 @@ void MainWindow::updateShortcuts() seq = QKeySequence::fromString(acc_keys[accID].seq); ui->actionMute_Unmute->setShortcut(seq); } - -void -MainWindow::adjustForForce43(const QSize &newWinSize) + +void +MainWindow::applyContentLayoutForCurrentState() { - // Only act in resizable mode with Force 4:3 enabled and not fullscreen - if (!(vid_resize == 1 && force_43 > 0) || video_fullscreen || s_adjustingForce43) - return; + auto applyFill = [this](const QRect& r){ + ui->stackedWidget->setGeometry(r); + ui->stackedWidget->onResize(r.width(), r.height()); + if (monitors[0].mon_scrnsz_x != r.width() || monitors[0].mon_scrnsz_y != r.height()) { + monitors[0].mon_scrnsz_x = r.width(); + monitors[0].mon_scrnsz_y = r.height(); + plat_resize_request(r.width(), r.height(), 0); + } + }; - s_adjustingForce43 = true; + auto apply43 = [this](const QRect& area){ + int areaW = area.width(); + int areaH = area.height(); + if (areaW <= 0 || areaH <= 0) return; - // Height consumed by menu/status/toolbars - int chromeH = menuBar()->height() - + (hide_status_bar ? 0 : statusBar()->height()) - + (hide_tool_bar ? 0 : ui->toolBar->height()); + int targetW = areaW; + int targetH = (areaW * 3) / 4; + if (targetH > areaH) { + targetH = areaH; + targetW = (areaH * 4) / 3; + } - // Compute client area size in device‑independent pixels - double dpr = (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.0); - int winW = newWinSize.width(); - int winH = newWinSize.height(); - int clientW = static_cast(winW / dpr); - int clientH = static_cast((winH - chromeH) / dpr); + const int x = area.x() + (areaW - targetW) / 2; + const int y = area.y() + (areaH - targetH) / 2; - if (clientW <= 0 || clientH <= 0) { - s_adjustingForce43 = false; - return; - } + ui->stackedWidget->setGeometry(x, y, targetW, targetH); + ui->stackedWidget->onResize(targetW, targetH); - // Decide which dimension the user changed most – adjust the other - int curW = static_cast(width() / dpr); - int curH = static_cast((height() - chromeH) / dpr); - bool widthChanged = std::abs(clientW - curW) >= std::abs(clientH - curH); + if (monitors[0].mon_scrnsz_x != targetW || monitors[0].mon_scrnsz_y != targetH) { + monitors[0].mon_scrnsz_x = targetW; + monitors[0].mon_scrnsz_y = targetH; + plat_resize_request(targetW, targetH, 0); + } + }; - int targetW, targetH; - if (widthChanged) { - // user dragged width – compute matching height for 4:3 - targetW = clientW; - targetH = (clientW * 3) / 4; - } else { - // user dragged height – compute matching width for 4:3 - targetH = clientH; - targetW = (clientH * 4) / 3; - } + QWidget *cw = this->centralWidget(); + if (!cw) return; - // Convert back to window size including chrome and apply - int newW = static_cast(targetW * dpr); - int newH = static_cast(targetH * dpr) + chromeH; - if (newW != winW || newH != winH) - resize(newW, newH); + const QRect area = cw->contentsRect(); - // Update emulator framebuffer size and notify platform - monitors[0].mon_scrnsz_x = targetW; - monitors[0].mon_scrnsz_y = targetH; - plat_resize_request(targetW, targetH, 0); + // Fullscreen always fills (legacy behavior) + if (video_fullscreen) { applyFill(area); return; } - // Allow renderer widget to grow and recompute scaling - ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - ui->stackedWidget->onResize(width(), height()); - - s_adjustingForce43 = false; + // Windowed: enforce 4:3 only when requested, otherwise fill + if (force_43 > 0) apply43(area); + else applyFill(area); } void @@ -1088,26 +1085,10 @@ MainWindow::resizeEvent(QResizeEvent *event) //qDebug() << pos().x() + event->size().width(); //qDebug() << pos().y() + event->size().height(); - // Enforce 4:3 aspect ratio in resizable mode when the option is set - adjustForForce43(event->size()); - - if (vid_resize == 1 || video_fullscreen) - return; + // Always let QMainWindow do its layout first + QMainWindow::resizeEvent(event); - 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); + applyContentLayoutForCurrentState(); } void @@ -1201,12 +1182,25 @@ MainWindow::showEvent(QShowEvent *event) monitors[0].mon_scrnsz_y = fixed_size_y; } if (window_remember && vid_resize == 1) { - ui->stackedWidget->setFixedSize(window_w, window_h); + const QSize target(window_w, window_h); + const QSize prevMin = ui->stackedWidget->minimumSize(); + const QSize prevMax = ui->stackedWidget->maximumSize(); + + ui->stackedWidget->setMinimumSize(target); + ui->stackedWidget->setMaximumSize(target); #ifndef Q_OS_MACOS QApplication::processEvents(); #endif this->adjustSize(); + + ui->stackedWidget->setMinimumSize(prevMin); + ui->stackedWidget->setMaximumSize(prevMax); + ui->stackedWidget->resize(target); } + + QTimer::singleShot(0, this, [this]{ + applyContentLayoutForCurrentState(); + }); } void @@ -1509,6 +1503,7 @@ MainWindow::on_actionFullscreen_triggered() { if (video_fullscreen > 0) { showNormal(); + QTimer::singleShot(0, this, [this]{ applyContentLayoutForCurrentState(); }); ui->menubar->show(); if (!hide_status_bar) ui->statusbar->show(); @@ -2146,16 +2141,7 @@ MainWindow::on_actionForce_4_3_display_ratio_triggered() { video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43); - // When turning on Force 4:3 in resizable mode, immediately snap to 4:3 - if (vid_resize == 1 && !video_fullscreen) { - ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - if (force_43 > 0) { - adjustForForce43(size()); - } else { - // Turning off: refresh renderer scaling - ui->stackedWidget->onResize(width(), height()); - } - } + QTimer::singleShot(0, this, [this]{ applyContentLayoutForCurrentState(); }); } void @@ -2524,4 +2510,3 @@ void MainWindow::on_actionCGA_composite_settings_triggered() isNonPause = false; config_save(); } - diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index f562c2ea9..77e8fe7c4 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -179,8 +179,8 @@ private: std::shared_ptr mm; static bool s_adjustingForce43; // guard against recursion - void adjustForForce43(const QSize &newWinSize); - + void applyContentLayoutForCurrentState(); + void updateShortcuts(); void processKeyboardInput(bool down, uint32_t keycode); #ifdef Q_OS_MACOS diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 6a9b9ea34..221af0d3f 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -39,6 +39,7 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> +#include <86box/bswap.h> #ifdef CLAMP # undef CLAMP @@ -80,6 +81,7 @@ enum { typedef struct mach64_t { mem_mapping_t linear_mapping; mem_mapping_t mmio_mapping; + mem_mapping_t linear_mapping_big_endian; mem_mapping_t mmio_linear_mapping; mem_mapping_t mmio_linear_mapping_2; @@ -98,6 +100,8 @@ typedef struct mach64_t { uint8_t pci_slot; uint8_t irq_state; + uint8_t on_board; + uint8_t pci_regs[256]; uint8_t int_line; @@ -272,7 +276,7 @@ typedef struct mach64_t { uint32_t cur_clr0; uint32_t cur_clr1; - uint32_t overlay_dat[1024]; + uint32_t overlay_dat[2048]; uint32_t overlay_graphics_key_clr; uint32_t overlay_graphics_key_msk; uint32_t overlay_video_key_clr; @@ -286,12 +290,17 @@ typedef struct mach64_t { uint32_t scaler_height_width; int scaler_format; int scaler_update; + int scaler_yuv_aper; uint32_t buf_offset[2]; uint32_t buf_pitch[2]; int overlay_v_acc; + uint32_t overlay_uv_addr; + uint32_t overlay_cur_y; + uint32_t overlay_base; + uint8_t thread_run; void *i2c; void *ddc; @@ -381,6 +390,9 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv); void mach64_ext_writew(uint32_t addr, uint16_t val, void *priv); void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv); +uint8_t mach64_readb_be(uint32_t addr, void *priv); +void mach64_writeb_be(uint32_t addr, uint8_t val, void *priv); + #ifdef ENABLE_MACH64_LOG int mach64_do_log = ENABLE_MACH64_LOG; @@ -591,6 +603,7 @@ mach64_updatemapping(mach64_t *mach64) mach64_log("Update mapping - PCI disabled\n"); mem_mapping_disable(&svga->mapping); mem_mapping_disable(&mach64->linear_mapping); + mem_mapping_disable(&mach64->linear_mapping_big_endian); mem_mapping_disable(&mach64->mmio_mapping); mem_mapping_disable(&mach64->mmio_linear_mapping); mem_mapping_disable(&mach64->mmio_linear_mapping_2); @@ -645,14 +658,16 @@ mach64_updatemapping(mach64_t *mach64) } } else { /*2*8 MB aperture*/ - mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); + mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 4096); + mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 4096), 4096); + mem_mapping_set_addr(&mach64->linear_mapping_big_endian, mach64->linear_base + (8 << 20), (8 << 20) - 0x1000); + mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x1000), 0x1000); } } else { mem_mapping_disable(&mach64->linear_mapping); mem_mapping_disable(&mach64->mmio_linear_mapping); mem_mapping_disable(&mach64->mmio_linear_mapping_2); + mem_mapping_disable(&mach64->linear_mapping_big_endian); } } @@ -2310,8 +2325,11 @@ mach64_vblank_start(svga_t *svga) svga->overlay.ena = (mach64->overlay_scale_cntl & OVERLAY_EN) && (overlay_cmp_mix != 1); - mach64->overlay_v_acc = 0; - mach64->scaler_update = 1; + mach64->overlay_v_acc = 0; + mach64->scaler_update = 1; + mach64->overlay_uv_addr = svga->overlay.addr; + mach64->overlay_cur_y = 0; + mach64->overlay_base = svga->overlay.addr; } uint8_t @@ -2389,6 +2407,10 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x4a: ret = mach64->scaler_format; break; + + case 0x4b: + ret = mach64->scaler_yuv_aper; + break; default: ret = 0xff; @@ -2558,7 +2580,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0xc7: READ8(addr, mach64->dac_cntl); - if (mach64->type == MACH64_VT2) { + if (mach64->type >= MACH64_VT2) { ret &= 0xf9; if (i2c_gpio_get_scl(mach64->i2c)) ret |= 0x04; @@ -2957,7 +2979,8 @@ mach64_ext_readw(uint32_t addr, void *priv) if (!(addr & 0x400)) { mach64_log("mach64_ext_readw: addr=%04x\n", addr); - ret = 0xffff; + ret = mach64_ext_readb(addr, priv); + ret |= mach64_ext_readb(addr + 1, priv) << 8; } else switch (addr & 0x3ff) { case 0xb4: @@ -2986,7 +3009,8 @@ mach64_ext_readl(uint32_t addr, void *priv) if (!(addr & 0x400)) { mach64_log("mach64_ext_readl: addr=%04x\n", addr); - ret = 0xffffffff; + ret = mach64_ext_readw(addr, priv); + ret |= mach64_ext_readw(addr + 2, priv) << 16; } else switch (addr & 0x3ff) { case 0x18: @@ -3087,6 +3111,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) case 0x4a: mach64->scaler_format = val & 0xf; break; + + case 0x4b: + mach64->scaler_yuv_aper = val; + break; case 0x80: case 0x81: @@ -4106,76 +4134,113 @@ mach64_int_hwcursor_draw(svga_t *svga, int displine) } \ } while (0) -#define DECODE_VYUY422() \ - do { \ - for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \ - uint8_t y1, y2; \ - int8_t u, v; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - y1 = src[0]; \ - u = src[1] - 0x80; \ - y2 = src[2]; \ - v = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359 * v) >> 8; \ - dG = (88 * u + 183 * v) >> 8; \ - dB = (453 * u) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \ - } \ +#define DECODE_VYUY422() \ + do { \ + for (x = 0; x < src_w; x += 1) { \ + uint8_t y1, y2; \ + int8_t u, v; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + y1 = src[0]; \ + u = src[1] - 0x80; \ + y2 = src[2]; \ + v = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * v) >> 8; \ + dG = (88 * u + 183 * v) >> 8; \ + dB = (453 * u) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \ + } \ } while (0) -#define DECODE_YVYU422() \ - do { \ - for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \ - uint8_t y1, y2; \ - int8_t u, v; \ - int dR, dG, dB; \ - int r, g, b; \ - \ - u = src[0] - 0x80; \ - y1 = src[1]; \ - v = src[2] - 0x80; \ - y2 = src[3]; \ - src += 4; \ - \ - dR = (359 * v) >> 8; \ - dG = (88 * u + 183 * v) >> 8; \ - dB = (453 * u) >> 8; \ - \ - r = y1 + dR; \ - CLAMP(r); \ - g = y1 - dG; \ - CLAMP(g); \ - b = y1 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \ - \ - r = y2 + dR; \ - CLAMP(r); \ - g = y2 - dG; \ - CLAMP(g); \ - b = y2 + dB; \ - CLAMP(b); \ - mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \ - } \ +#define DECODE_YVYU422() \ + do { \ + for (x = 0; x < src_w; x += 1) { \ + uint8_t y1, y2; \ + int8_t u, v; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + u = src[0] - 0x80; \ + y1 = src[1]; \ + v = src[2] - 0x80; \ + y2 = src[3]; \ + src += 4; \ + \ + dR = (359 * v) >> 8; \ + dG = (88 * u + 183 * v) >> 8; \ + dB = (453 * u) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \ + } \ + } while (0) + +#define DECODE_YUV12_PACKED() \ + do { \ + for (x = 0; x < src_w; x += 1) { \ + uint8_t y1, y2; \ + int8_t u, v; \ + int dR, dG, dB; \ + int r, g, b; \ + \ + u = uvsrc[3] - 0x80; \ + y1 = src[0]; \ + v = uvsrc[2] - 0x80; \ + y2 = src[1]; \ + src += 4; \ + uvsrc += 4; \ + \ + dR = (359 * v) >> 8; \ + dG = (88 * u + 183 * v) >> 8; \ + dB = (453 * u) >> 8; \ + \ + r = y1 + dR; \ + CLAMP(r); \ + g = y1 - dG; \ + CLAMP(g); \ + b = y1 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \ + \ + r = y2 + dR; \ + CLAMP(r); \ + g = y2 - dG; \ + CLAMP(g); \ + b = y2 + dB; \ + CLAMP(b); \ + mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \ + } \ } while (0) void @@ -4185,11 +4250,13 @@ mach64_overlay_draw(svga_t *svga, int displine) int x; int h_acc = 0; int h_max = (mach64->scaler_height_width >> 16) & 0x3ff; + int src_w = h_max; int h_inc = mach64->overlay_scale_inc >> 16; int v_max = mach64->scaler_height_width & 0x3ff; int v_inc = mach64->overlay_scale_inc & 0xffff; uint32_t *p; uint8_t *src = &svga->vram[svga->overlay.addr]; + uint8_t *uvsrc = src; int old_y = mach64->overlay_v_acc; int y_diff; int video_key_fn = mach64->overlay_key_cntl & 5; @@ -4198,6 +4265,11 @@ mach64_overlay_draw(svga_t *svga, int displine) p = &buffer32->line[displine][svga->x_add + mach64->svga.overlay_latch.x]; + if (mach64->overlay_cur_y >= 2) { + /* Avoid corrupt UV data on YUV12 packed modes */ + uvsrc = &svga->vram[mach64->overlay_base + svga->overlay.pitch * 2 * (!(mach64->overlay_cur_y & 1) ? (mach64->overlay_cur_y + 1) : mach64->overlay_cur_y)]; + } + if (mach64->scaler_update) { switch (mach64->scaler_format) { case 0x3: @@ -4209,6 +4281,9 @@ mach64_overlay_draw(svga_t *svga, int displine) case 0x6: DECODE_ARGB8888(); break; + case 0xa: + DECODE_YUV12_PACKED(); + break; case 0xb: DECODE_VYUY422(); break; @@ -4217,7 +4292,7 @@ mach64_overlay_draw(svga_t *svga, int displine) break; default: - mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format); + pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format); /*Fill buffer with something recognisably wrong*/ for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++) mach64->overlay_dat[x] = 0xff00ff; @@ -4354,6 +4429,7 @@ mach64_overlay_draw(svga_t *svga, int displine) svga->overlay.addr += svga->overlay.pitch * 2 * y_diff; mach64->scaler_update = y_diff; + mach64->overlay_cur_y += y_diff; } static void @@ -4389,7 +4465,7 @@ mach64_io_remove(mach64_t *mach64) io_removehandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) - io_removehandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); + io_removehandler(mach64->block_decoded_io, 0x0100, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); } static void @@ -4429,7 +4505,7 @@ mach64_io_set(mach64_t *mach64) io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64); if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000) - io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); + io_sethandler(mach64->block_decoded_io, 0x0100, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64); } static uint8_t @@ -4478,7 +4554,6 @@ static void mach64_write_linear(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; - cycles -= svga->monitor->mon_video_timing_write_b; addr &= svga->decode_mask; @@ -4507,10 +4582,38 @@ mach64_writew_linear(uint32_t addr, uint16_t val, void *priv) static void mach64_writel_linear(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *) priv; + svga_t *svga = (svga_t *) priv; + mach64_t *mach64 = (mach64_t *) svga->priv; cycles -= svga->monitor->mon_video_timing_write_l; + if (((mach64->scaler_yuv_aper >> 4) & 0xc) && !!(addr & 0x800000) == !(mach64->scaler_yuv_aper & 0x20)) { + uint32_t offset_from_base = addr & 0x7FFFFF; + if (addr & 0x800000) bswap32s(&val); + if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x4) { // Y plane + offset_from_base <<= 1; + svga->vram[offset_from_base & svga->vram_mask] = (val & 0xFF); + svga->vram[(offset_from_base + 1) & svga->vram_mask] = ((val >> 8) & 0xFF); + svga->vram[(offset_from_base + 4) & svga->vram_mask] = ((val >> 16) & 0xFF); + svga->vram[(offset_from_base + 5) & svga->vram_mask] = ((val >> 24) & 0xFF); + } + else if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x8 || ((mach64->scaler_yuv_aper >> 4) & 0xc) == 0xc) { + offset_from_base <<= 2; + if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x8) { // U plane + svga->vram[(offset_from_base + 3) & svga->vram_mask] = (val & 0xFF); + svga->vram[(offset_from_base + 7) & svga->vram_mask] = ((val >> 8) & 0xFF); + svga->vram[(offset_from_base + 11) & svga->vram_mask] = ((val >> 16) & 0xFF); + svga->vram[(offset_from_base + 15) & svga->vram_mask] = ((val >> 24) & 0xFF); + } else { // V plane + svga->vram[(offset_from_base + 2) & svga->vram_mask] = (val & 0xFF); + svga->vram[(offset_from_base + 6) & svga->vram_mask] = ((val >> 8) & 0xFF); + svga->vram[(offset_from_base + 10) & svga->vram_mask] = ((val >> 16) & 0xFF); + svga->vram[(offset_from_base + 14) & svga->vram_mask] = ((val >> 24) & 0xFF); + } + } + return; + } + addr &= svga->decode_mask; if (addr >= svga->vram_max) return; @@ -4519,6 +4622,42 @@ mach64_writel_linear(uint32_t addr, uint32_t val, void *priv) *(uint32_t *) &svga->vram[addr] = val; } +uint8_t +mach64_readb_be(uint32_t addr, void *priv) +{ + return mach64_read_linear(addr, priv); +} + +uint16_t +mach64_readw_be(uint32_t addr, void *priv) +{ + return bswap16(mach64_readw_linear(addr, priv)); +} + +uint32_t +mach64_readl_be(uint32_t addr, void *priv) +{ + return bswap32(mach64_readl_linear(addr, priv)); +} + +void +mach64_writeb_be(uint32_t addr, uint8_t val, void *priv) +{ + return mach64_write_linear(addr, val, priv); +} + +void +mach64_writew_be(uint32_t addr, uint16_t val, void *priv) +{ + return mach64_writew_linear(addr, bswap16(val), priv); +} + +void +mach64_writel_be(uint32_t addr, uint32_t val, void *priv) +{ + return mach64_writel_linear(addr, bswap32(val), priv); +} + uint8_t mach64_pci_read(UNUSED(int func), int addr, void *priv) { @@ -4564,30 +4703,31 @@ mach64_pci_read(UNUSED(int func), int addr, void *priv) return mach64->linear_base >> 24; case 0x14: - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) return 0x01; /*Block decoded IO address*/ return 0x00; case 0x15: - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) return mach64->block_decoded_io >> 8; return 0x00; case 0x16: - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) return mach64->block_decoded_io >> 16; return 0x00; case 0x17: - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) return mach64->block_decoded_io >> 24; return 0x00; + case 0x30: - return mach64->pci_regs[0x30] & 0x01; /*BIOS ROM address*/ + return (mach64->on_board) ? 0 : (mach64->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ case 0x31: return 0x00; case 0x32: - return mach64->pci_regs[0x32]; + return (mach64->on_board) ? 0 : mach64->pci_regs[0x32]; case 0x33: - return mach64->pci_regs[0x33]; + return (mach64->on_board) ? 0 : mach64->pci_regs[0x33]; case 0x3c: return mach64->int_line; @@ -4619,7 +4759,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x12: - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) val = 0; mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16); mach64_updatemapping(mach64); @@ -4630,16 +4770,16 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x15: - if (mach64->type == MACH64_VT2) { + if (mach64->type >= MACH64_VT2) { if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_remove(mach64); - mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xfc) << 8); + mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xff) << 8); if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_set(mach64); } break; case 0x16: - if (mach64->type == MACH64_VT2) { + if (mach64->type >= MACH64_VT2) { if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_remove(mach64); mach64->block_decoded_io = (mach64->block_decoded_io & 0xff00fc00) | (val << 16); @@ -4648,7 +4788,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) } break; case 0x17: - if (mach64->type == MACH64_VT2) { + if (mach64->type >= MACH64_VT2) { if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_remove(mach64); mach64->block_decoded_io = (mach64->block_decoded_io & 0x00fffc00) | (val << 24); @@ -4660,6 +4800,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) case 0x30: case 0x32: case 0x33: + if (mach64->on_board) return; mach64->pci_regs[addr] = val; if (mach64->pci_regs[0x30] & 0x01) { uint32_t biosaddr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); @@ -4679,7 +4820,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_remove(mach64); mach64->io_base = val & 0x03; - if (mach64->type == MACH64_VT2) + if (mach64->type >= MACH64_VT2) mach64->use_block_decoded_io = val & 0x04; if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) mach64_io_set(mach64); @@ -4700,7 +4841,7 @@ mach64_common_init(const device_t *info) svga = &mach64->svga; mach64->type = info->local & 0xff; - mach64->vram_size = device_get_config_int("memory"); + mach64->vram_size = (info->local & (1 << 20)) ? 4 : device_get_config_int("memory"); mach64->vram_mask = (mach64->vram_size << 20) - 1; if (mach64->type > MACH64_GX) @@ -4717,9 +4858,10 @@ mach64_common_init(const device_t *info) mach64_overlay_draw); mem_mapping_add(&mach64->linear_mapping, 0, 0, mach64_read_linear, mach64_readw_linear, mach64_readl_linear, mach64_write_linear, mach64_writew_linear, mach64_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); + mem_mapping_add(&mach64->linear_mapping_big_endian, 0, 0, mach64_readb_be, mach64_readw_be, mach64_readl_be, mach64_writeb_be, mach64_writew_be, mach64_writel_be, NULL, MEM_MAPPING_EXTERNAL, svga); mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); mem_mapping_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); - mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); + mem_mapping_add(&mach64->mmio_mapping, 0xbf000, 0x1000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64); mem_mapping_disable(&mach64->mmio_mapping); mach64_io_set(mach64); diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index d9e1d91ef..ac96aedef 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -1952,9 +1952,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x8190: virge->streams.sec_ctrl = val; - virge->streams.dda_horiz_accumulator = val & 0xfff; - if (val & 0x1000) - virge->streams.dda_horiz_accumulator |= ~0xfff; + virge->streams.dda_horiz_accumulator = val & 0x7ff; + if (val & 0x800) + virge->streams.dda_horiz_accumulator |= ~0x7ff; virge->streams.sdif = (val >> 24) & 7; break; @@ -2030,9 +2030,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) virge->streams.k2_vert_scale |= ~0x7ff; break; case 0x81e8: - virge->streams.dda_vert_accumulator = val & 0xfff; - if (val & 0x1000) - virge->streams.dda_vert_accumulator |= ~0xfff; + virge->streams.dda_vert_accumulator = val & 0x7ff; + if (val & 0x800) + virge->streams.dda_vert_accumulator |= ~0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount;